/* packet-windows-common.c
 * Routines for dissecting various Windows data types
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "config.h"


#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/exceptions.h>
#include "packet-smb-sidsnooping.h"
#include "packet-windows-common.h"
#include "packet-smb.h"	/* for "sid_name_snooping" */

/* The types used in [MS-DTYP] v20180912 should be interpreted as
 * follows (all multi-byte integer types are little endian):
 * typedef uint8_t MS_BYTE;
 * typedef uint16_t MS_WORD;
 * typedef uint32_t MS_DWORD;
 * typedef uint64_t MS_QWORD;
 * typedef uint64_t MS_ULONG64;
 * typedef uint64_t MS_DWORD64;
 * typedef int64_t MS_LONG64;
 */

enum cond_ace_token {
#define DEF_COND_ACE_TOKEN(VAL, VAR, STR) COND_ACE_TOKEN_ ## VAR = VAL,
#define DEF_COND_ACE_TOKEN_WITH_DATA DEF_COND_ACE_TOKEN
#include "cond_ace_token_enum.h"
	COND_ACE_TOKEN_UNKNOWN = -1
};

static const value_string ace_cond_token_vals[] = {
#define DEF_COND_ACE_TOKEN(VAL, VAR, STR) {VAL, STR},
#define DEF_COND_ACE_TOKEN_WITH_DATA DEF_COND_ACE_TOKEN
#include "cond_ace_token_enum.h"
	{ 0, NULL }
};

static bool
ace_cond_token_has_data(uint8_t token) {
	switch (token) {
#define DEF_COND_ACE_TOKEN(VAL, VAR, STR)
#define DEF_COND_ACE_TOKEN_WITH_DATA(VAL, VAR, STR) case VAL:
#include "cond_ace_token_enum.h"
		return true;
	}
	return false;
}

static const value_string ace_cond_base_vals[] = {
	{ 0x01, "OCT" },
	{ 0x02, "DEC" },
	{ 0x03, "HEX" },
	{ 0, NULL }
};

static const value_string ace_cond_sign_vals[] = {
	{ 0x01, "PLUS" },
	{ 0x02, "MINUS" },
	{ 0x03, "NONE" },
	{ 0, NULL }
};


#define CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64           0x0001
#define CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64          0x0002
#define CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING          0x0003
#define CLAIM_SECURITY_ATTRIBUTE_TYPE_SID             0x0005
#define CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN         0x0006
#define CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING    0x0010

static const value_string ace_sra_type_vals[] = {
	{ CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64, "INT64" },
	{ CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64, "UINT64" },
	{ CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING, "STRING" },
	{ CLAIM_SECURITY_ATTRIBUTE_TYPE_SID, "SID"},
	{ CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN, "BOOLEAN" },
	{ CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING, "OCTET_STRING" },
	{ 0, NULL }
};

static int hf_nt_sec_desc_revision;
static int hf_nt_sec_desc_type_owner_defaulted;
static int hf_nt_sec_desc_type_group_defaulted;
static int hf_nt_sec_desc_type_dacl_present;
static int hf_nt_sec_desc_type_dacl_defaulted;
static int hf_nt_sec_desc_type_sacl_present;
static int hf_nt_sec_desc_type_sacl_defaulted;
static int hf_nt_sec_desc_type_dacl_trusted;
static int hf_nt_sec_desc_type_server_security;
static int hf_nt_sec_desc_type_dacl_auto_inherit_req;
static int hf_nt_sec_desc_type_sacl_auto_inherit_req;
static int hf_nt_sec_desc_type_dacl_auto_inherited;
static int hf_nt_sec_desc_type_sacl_auto_inherited;
static int hf_nt_sec_desc_type_dacl_protected;
static int hf_nt_sec_desc_type_sacl_protected;
static int hf_nt_sec_desc_type_rm_control_valid;
static int hf_nt_sec_desc_type_self_relative;
static int hf_nt_sid;
static int hf_nt_sid_revision;
static int hf_nt_sid_num_auth;
static int hf_nt_sid_auth_dec;
static int hf_nt_sid_auth_hex;
static int hf_nt_sid_subauth;
static int hf_nt_sid_rid_dec;
static int hf_nt_sid_rid_hex;
static int hf_nt_sid_wkwn;
static int hf_nt_sid_domain;
static int hf_nt_acl_revision;
static int hf_nt_acl_size;
static int hf_nt_acl_num_aces;
static int hf_nt_ace_flags_object_inherit;
static int hf_nt_ace_flags_container_inherit;
static int hf_nt_ace_flags_non_propagate_inherit;
static int hf_nt_ace_flags_inherit_only;
static int hf_nt_ace_flags_inherited_ace;
static int hf_nt_ace_flags_successful_access;
static int hf_nt_ace_flags_failed_access;
static int hf_nt_ace_type;
static int hf_nt_ace_size;
static int hf_nt_ace_flags_object_type_present;
static int hf_nt_ace_flags_inherited_object_type_present;
static int hf_nt_ace_guid;
static int hf_nt_ace_inherited_guid;

/* Conditional ACE dissect */
static int hf_nt_ace_cond;
static int hf_nt_ace_cond_token;
static int hf_nt_ace_cond_sign;
static int hf_nt_ace_cond_base;
static int hf_nt_ace_cond_value_int8;
static int hf_nt_ace_cond_value_int16;
static int hf_nt_ace_cond_value_int32;
static int hf_nt_ace_cond_value_int64;
static int hf_nt_ace_cond_value_string;
static int hf_nt_ace_cond_value_octet_string;
static int hf_nt_ace_cond_local_attr;
static int hf_nt_ace_cond_user_attr;
static int hf_nt_ace_cond_resource_attr;
static int hf_nt_ace_cond_device_attr;

/* System Resource Attribute ACE dissect */
static int hf_nt_ace_sra;
static int hf_nt_ace_sra_name_offset;
static int hf_nt_ace_sra_name;
static int hf_nt_ace_sra_type;
static int hf_nt_ace_sra_reserved;
static int hf_nt_ace_sra_flags;
static int hf_nt_ace_sra_flags_manual;
static int hf_nt_ace_sra_flags_policy_derived;
static int hf_nt_ace_sra_flags_non_inheritable;
static int hf_nt_ace_sra_flags_case_sensitive;
static int hf_nt_ace_sra_flags_deny_only;
static int hf_nt_ace_sra_flags_disabled_by_default;
static int hf_nt_ace_sra_flags_disabled;
static int hf_nt_ace_sra_flags_mandatory;
static int hf_nt_ace_sra_value_count;
static int hf_nt_ace_sra_value_offset;
static int hf_nt_ace_sra_value_int64;
static int hf_nt_ace_sra_value_uint64;
static int hf_nt_ace_sra_value_string;
static int hf_nt_ace_sra_value_sid;
static int hf_nt_ace_sra_value_boolean;
static int hf_nt_ace_sra_value_octet_string;

static int hf_nt_security_information_sacl;
static int hf_nt_security_information_dacl;
static int hf_nt_security_information_group;
static int hf_nt_security_information_owner;

/* Generated from convert_proto_tree_add_text.pl */
static int hf_nt_security_information;
static int hf_nt_sec_desc_type;
static int hf_nt_offset_to_dacl;
static int hf_nt_offset_to_owner_sid;
static int hf_nt_ace_flags_object;
static int hf_nt_offset_to_group_sid;
static int hf_nt_ace_flags;
static int hf_nt_offset_to_sacl;

static int ett_nt_sec_desc;
static int ett_nt_sec_desc_type;
static int ett_nt_sid;
static int ett_nt_acl;
static int ett_nt_ace;
static int ett_nt_ace_flags;
static int ett_nt_ace_object;
static int ett_nt_ace_object_flags;
static int ett_nt_security_information;
static int ett_nt_ace_cond;
static int ett_nt_ace_cond_data;
static int ett_nt_ace_sra;
static int ett_nt_ace_sra_flags;
static int ett_nt_ace_sra_value_offsets;
static int ett_nt_ace_sra_values;

static expert_field ei_nt_owner_sid_beyond_data;
static expert_field ei_nt_owner_sid_beyond_reassembled_data;
static expert_field ei_nt_ace_extends_beyond_data;
static expert_field ei_nt_ace_extends_beyond_reassembled_data;
static expert_field ei_nt_group_sid_beyond_data;
static expert_field ei_nt_group_sid_beyond_reassembled_data;
static expert_field ei_nt_item_offs_out_of_range;


/* WERR error codes */

VALUE_STRING_ARRAY2(WERR_errors);
value_string_ext WERR_errors_ext = VALUE_STRING_EXT_INIT(WERR_errors);

/*
 * HRES error codes.
 */

VALUE_STRING_ARRAY2(HRES_errors);
value_string_ext HRES_errors_ext = VALUE_STRING_EXT_INIT(HRES_errors);


/*
 * DOS error codes.
 */

VALUE_STRING_ARRAY(DOS_errors);
value_string_ext DOS_errors_ext = VALUE_STRING_EXT_INIT(DOS_errors);

/*
 * NT error codes.
 *
 * From
 *
 *	https://web.archive.org/web/20100503121824/http://www.wildpackets.com/elements/misc/SMB_NT_Status_Codes.txt
 *
 * See also MS-ERREF section 2.3.1 "NTSTATUS Values":
 *
 *	https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
 */
static const value_string NT_errors[] = {
	{ 0x00000000, "STATUS_SUCCESS" },
	/*{ 0x00000000, "STATUS_WAIT_0" }, */
	{ 0x00000001, "STATUS_WAIT_1" },
	{ 0x00000002, "STATUS_WAIT_2" },
	{ 0x00000003, "STATUS_WAIT_3" },
	{ 0x0000003F, "STATUS_WAIT_63" },
	{ 0x00000080, "STATUS_ABANDONED" },
	/*{ 0x00000080, "STATUS_ABANDONED_WAIT_0" },*/
	{ 0x000000BF, "STATUS_ABANDONED_WAIT_63" },
	{ 0x000000C0, "STATUS_USER_APC" },
	{ 0x00000100, "STATUS_KERNEL_APC" },
	{ 0x00000101, "STATUS_ALERTED" },
	{ 0x00000102, "STATUS_TIMEOUT" },
	{ 0x00000103, "STATUS_PENDING" },
	{ 0x00000104, "STATUS_REPARSE" },
	{ 0x00000105, "STATUS_MORE_ENTRIES" },
	{ 0x00000106, "STATUS_NOT_ALL_ASSIGNED" },
	{ 0x00000107, "STATUS_SOME_NOT_MAPPED" },
	{ 0x00000108, "STATUS_OPLOCK_BREAK_IN_PROGRESS" },
	{ 0x00000109, "STATUS_VOLUME_MOUNTED" },
	{ 0x0000010A, "STATUS_RXACT_COMMITTED" },
	{ 0x0000010B, "STATUS_NOTIFY_CLEANUP" },
	{ 0x0000010C, "STATUS_NOTIFY_ENUM_DIR" },
	{ 0x0000010D, "STATUS_NO_QUOTAS_FOR_ACCOUNT" },
	{ 0x0000010E, "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED" },
	{ 0x00000110, "STATUS_PAGE_FAULT_TRANSITION" },
	{ 0x00000111, "STATUS_PAGE_FAULT_DEMAND_ZERO" },
	{ 0x00000112, "STATUS_PAGE_FAULT_COPY_ON_WRITE" },
	{ 0x00000113, "STATUS_PAGE_FAULT_GUARD_PAGE" },
	{ 0x00000114, "STATUS_PAGE_FAULT_PAGING_FILE" },
	{ 0x00000115, "STATUS_CACHE_PAGE_LOCKED" },
	{ 0x00000116, "STATUS_CRASH_DUMP" },
	{ 0x00000117, "STATUS_BUFFER_ALL_ZEROS" },
	{ 0x00000118, "STATUS_REPARSE_OBJECT" },
	{ 0x0000045C, "STATUS_NO_SHUTDOWN_IN_PROGRESS" },
	{ 0x40000000, "STATUS_OBJECT_NAME_EXISTS" },
	{ 0x40000001, "STATUS_THREAD_WAS_SUSPENDED" },
	{ 0x40000002, "STATUS_WORKING_SET_LIMIT_RANGE" },
	{ 0x40000003, "STATUS_IMAGE_NOT_AT_BASE" },
	{ 0x40000004, "STATUS_RXACT_STATE_CREATED" },
	{ 0x40000005, "STATUS_SEGMENT_NOTIFICATION" },
	{ 0x40000006, "STATUS_LOCAL_USER_SESSION_KEY" },
	{ 0x40000007, "STATUS_BAD_CURRENT_DIRECTORY" },
	{ 0x40000008, "STATUS_SERIAL_MORE_WRITES" },
	{ 0x40000009, "STATUS_REGISTRY_RECOVERED" },
	{ 0x4000000A, "STATUS_FT_READ_RECOVERY_FROM_BACKUP" },
	{ 0x4000000B, "STATUS_FT_WRITE_RECOVERY" },
	{ 0x4000000C, "STATUS_SERIAL_COUNTER_TIMEOUT" },
	{ 0x4000000D, "STATUS_NULL_LM_PASSWORD" },
	{ 0x4000000E, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH" },
	{ 0x4000000F, "STATUS_RECEIVE_PARTIAL" },
	{ 0x40000010, "STATUS_RECEIVE_EXPEDITED" },
	{ 0x40000011, "STATUS_RECEIVE_PARTIAL_EXPEDITED" },
	{ 0x40000012, "STATUS_EVENT_DONE" },
	{ 0x40000013, "STATUS_EVENT_PENDING" },
	{ 0x40000014, "STATUS_CHECKING_FILE_SYSTEM" },
	{ 0x40000015, "STATUS_FATAL_APP_EXIT" },
	{ 0x40000016, "STATUS_PREDEFINED_HANDLE" },
	{ 0x40000017, "STATUS_WAS_UNLOCKED" },
	{ 0x40000018, "STATUS_SERVICE_NOTIFICATION" },
	{ 0x40000019, "STATUS_WAS_LOCKED" },
	{ 0x4000001A, "STATUS_LOG_HARD_ERROR" },
	{ 0x4000001B, "STATUS_ALREADY_WIN32" },
	{ 0x4000001C, "STATUS_WX86_UNSIMULATE" },
	{ 0x4000001D, "STATUS_WX86_CONTINUE" },
	{ 0x4000001E, "STATUS_WX86_SINGLE_STEP" },
	{ 0x4000001F, "STATUS_WX86_BREAKPOINT" },
	{ 0x40000020, "STATUS_WX86_EXCEPTION_CONTINUE" },
	{ 0x40000021, "STATUS_WX86_EXCEPTION_LASTCHANCE" },
	{ 0x40000022, "STATUS_WX86_EXCEPTION_CHAIN" },
	{ 0x40000023, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE" },
	{ 0x40000024, "STATUS_NO_YIELD_PERFORMED" },
	{ 0x40000025, "STATUS_TIMER_RESUME_IGNORED" },
	{ 0x40000294, "STATUS_WAKE_SYSTEM" },
	{ 0x40020056, "RPC_NT_UUID_LOCAL_ONLY" },
	{ 0x400200AF, "RPC_NT_SEND_INCOMPLETE" },
	{ 0x80000001, "STATUS_GUARD_PAGE_VIOLATION" },
	{ 0x80000002, "STATUS_DATATYPE_MISALIGNMENT" },
	{ 0x80000003, "STATUS_BREAKPOINT" },
	{ 0x80000004, "STATUS_SINGLE_STEP" },
	{ 0x80000005, "STATUS_BUFFER_OVERFLOW" },
	{ 0x80000006, "STATUS_NO_MORE_FILES" },
	{ 0x80000007, "STATUS_WAKE_SYSTEM_DEBUGGER" },
	{ 0x8000000A, "STATUS_HANDLES_CLOSED" },
	{ 0x8000000B, "STATUS_NO_INHERITANCE" },
	{ 0x8000000C, "STATUS_GUID_SUBSTITUTION_MADE" },
	{ 0x8000000D, "STATUS_PARTIAL_COPY" },
	{ 0x8000000E, "STATUS_DEVICE_PAPER_EMPTY" },
	{ 0x8000000F, "STATUS_DEVICE_POWERED_OFF" },
	{ 0x80000010, "STATUS_DEVICE_OFF_LINE" },
	{ 0x80000011, "STATUS_DEVICE_BUSY" },
	{ 0x80000012, "STATUS_NO_MORE_EAS" },
	{ 0x80000013, "STATUS_INVALID_EA_NAME" },
	{ 0x80000014, "STATUS_EA_LIST_INCONSISTENT" },
	{ 0x80000015, "STATUS_INVALID_EA_FLAG" },
	{ 0x80000016, "STATUS_VERIFY_REQUIRED" },
	{ 0x80000017, "STATUS_EXTRANEOUS_INFORMATION" },
	{ 0x80000018, "STATUS_RXACT_COMMIT_NECESSARY" },
	{ 0x8000001A, "STATUS_NO_MORE_ENTRIES" },
	{ 0x8000001B, "STATUS_FILEMARK_DETECTED" },
	{ 0x8000001C, "STATUS_MEDIA_CHANGED" },
	{ 0x8000001D, "STATUS_BUS_RESET" },
	{ 0x8000001E, "STATUS_END_OF_MEDIA" },
	{ 0x8000001F, "STATUS_BEGINNING_OF_MEDIA" },
	{ 0x80000020, "STATUS_MEDIA_CHECK" },
	{ 0x80000021, "STATUS_SETMARK_DETECTED" },
	{ 0x80000022, "STATUS_NO_DATA_DETECTED" },
	{ 0x80000023, "STATUS_REDIRECTOR_HAS_OPEN_HANDLES" },
	{ 0x80000024, "STATUS_SERVER_HAS_OPEN_HANDLES" },
	{ 0x80000025, "STATUS_ALREADY_DISCONNECTED" },
	{ 0x80000026, "STATUS_LONGJUMP" },
	{ 0x8000002D, "STATUS_STOPPED_ON_SYMLINK" },
	{ 0x80000288, "STATUS_DEVICE_REQUIRES_CLEANING" },
	{ 0x80000289, "STATUS_DEVICE_DOOR_OPEN" },
	{ 0x80040111, "MAPI_E_LOGON_FAILED" },
	{ 0x80090300, "SEC_E_INSUFFICIENT_MEMORY" },
	{ 0x80090301, "SEC_E_INVALID_HANDLE" },
	{ 0x80090302, "SEC_E_UNSUPPORTED_FUNCTION" },
	{ 0x8009030B, "SEC_E_NO_IMPERSONATION" },
	{ 0x8009030D, "SEC_E_UNKNOWN_CREDENTIALS" },
	{ 0x8009030E, "SEC_E_NO_CREDENTIALS" },
	{ 0x8009030F, "SEC_E_MESSAGE_ALTERED" },
	{ 0x80090310, "SEC_E_OUT_OF_SEQUENCE" },
	{ 0x80090311, "SEC_E_NO_AUTHENTICATING_AUTHORITY" },
	{ 0xC0000001, "STATUS_UNSUCCESSFUL" },
	{ 0xC0000002, "STATUS_NOT_IMPLEMENTED" },
	{ 0xC0000003, "STATUS_INVALID_INFO_CLASS" },
	{ 0xC0000004, "STATUS_INFO_LENGTH_MISMATCH" },
	{ 0xC0000005, "STATUS_ACCESS_VIOLATION" },
	{ 0xC0000006, "STATUS_IN_PAGE_ERROR" },
	{ 0xC0000007, "STATUS_PAGEFILE_QUOTA" },
	{ 0xC0000008, "STATUS_INVALID_HANDLE" },
	{ 0xC0000009, "STATUS_BAD_INITIAL_STACK" },
	{ 0xC000000A, "STATUS_BAD_INITIAL_PC" },
	{ 0xC000000B, "STATUS_INVALID_CID" },
	{ 0xC000000C, "STATUS_TIMER_NOT_CANCELED" },
	{ 0xC000000D, "STATUS_INVALID_PARAMETER" },
	{ 0xC000000E, "STATUS_NO_SUCH_DEVICE" },
	{ 0xC000000F, "STATUS_NO_SUCH_FILE" },
	{ 0xC0000010, "STATUS_INVALID_DEVICE_REQUEST" },
	{ 0xC0000011, "STATUS_END_OF_FILE" },
	{ 0xC0000012, "STATUS_WRONG_VOLUME" },
	{ 0xC0000013, "STATUS_NO_MEDIA_IN_DEVICE" },
	{ 0xC0000014, "STATUS_UNRECOGNIZED_MEDIA" },
	{ 0xC0000015, "STATUS_NONEXISTENT_SECTOR" },
	{ 0xC0000016, "STATUS_MORE_PROCESSING_REQUIRED" },
	{ 0xC0000017, "STATUS_NO_MEMORY" },
	{ 0xC0000018, "STATUS_CONFLICTING_ADDRESSES" },
	{ 0xC0000019, "STATUS_NOT_MAPPED_VIEW" },
	{ 0xC000001A, "STATUS_UNABLE_TO_FREE_VM" },
	{ 0xC000001B, "STATUS_UNABLE_TO_DELETE_SECTION" },
	{ 0xC000001C, "STATUS_INVALID_SYSTEM_SERVICE" },
	{ 0xC000001D, "STATUS_ILLEGAL_INSTRUCTION" },
	{ 0xC000001E, "STATUS_INVALID_LOCK_SEQUENCE" },
	{ 0xC000001F, "STATUS_INVALID_VIEW_SIZE" },
	{ 0xC0000020, "STATUS_INVALID_FILE_FOR_SECTION" },
	{ 0xC0000021, "STATUS_ALREADY_COMMITTED" },
	{ 0xC0000022, "STATUS_ACCESS_DENIED" },
	{ 0xC0000023, "STATUS_BUFFER_TOO_SMALL" },
	{ 0xC0000024, "STATUS_OBJECT_TYPE_MISMATCH" },
	{ 0xC0000025, "STATUS_NONCONTINUABLE_EXCEPTION" },
	{ 0xC0000026, "STATUS_INVALID_DISPOSITION" },
	{ 0xC0000027, "STATUS_UNWIND" },
	{ 0xC0000028, "STATUS_BAD_STACK" },
	{ 0xC0000029, "STATUS_INVALID_UNWIND_TARGET" },
	{ 0xC000002A, "STATUS_NOT_LOCKED" },
	{ 0xC000002B, "STATUS_PARITY_ERROR" },
	{ 0xC000002C, "STATUS_UNABLE_TO_DECOMMIT_VM" },
	{ 0xC000002D, "STATUS_NOT_COMMITTED" },
	{ 0xC000002E, "STATUS_INVALID_PORT_ATTRIBUTES" },
	{ 0xC000002F, "STATUS_PORT_MESSAGE_TOO_LONG" },
	{ 0xC0000030, "STATUS_INVALID_PARAMETER_MIX" },
	{ 0xC0000031, "STATUS_INVALID_QUOTA_LOWER" },
	{ 0xC0000032, "STATUS_DISK_CORRUPT_ERROR" },
	{ 0xC0000033, "STATUS_OBJECT_NAME_INVALID" },
	{ 0xC0000034, "STATUS_OBJECT_NAME_NOT_FOUND" },
	{ 0xC0000035, "STATUS_OBJECT_NAME_COLLISION" },
	{ 0xC0000037, "STATUS_PORT_DISCONNECTED" },
	{ 0xC0000038, "STATUS_DEVICE_ALREADY_ATTACHED" },
	{ 0xC0000039, "STATUS_OBJECT_PATH_INVALID" },
	{ 0xC000003A, "STATUS_OBJECT_PATH_NOT_FOUND" },
	{ 0xC000003B, "STATUS_OBJECT_PATH_SYNTAX_BAD" },
	{ 0xC000003C, "STATUS_DATA_OVERRUN" },
	{ 0xC000003D, "STATUS_DATA_LATE_ERROR" },
	{ 0xC000003E, "STATUS_DATA_ERROR" },
	{ 0xC000003F, "STATUS_CRC_ERROR" },
	{ 0xC0000040, "STATUS_SECTION_TOO_BIG" },
	{ 0xC0000041, "STATUS_PORT_CONNECTION_REFUSED" },
	{ 0xC0000042, "STATUS_INVALID_PORT_HANDLE" },
	{ 0xC0000043, "STATUS_SHARING_VIOLATION" },
	{ 0xC0000044, "STATUS_QUOTA_EXCEEDED" },
	{ 0xC0000045, "STATUS_INVALID_PAGE_PROTECTION" },
	{ 0xC0000046, "STATUS_MUTANT_NOT_OWNED" },
	{ 0xC0000047, "STATUS_SEMAPHORE_LIMIT_EXCEEDED" },
	{ 0xC0000048, "STATUS_PORT_ALREADY_SET" },
	{ 0xC0000049, "STATUS_SECTION_NOT_IMAGE" },
	{ 0xC000004A, "STATUS_SUSPEND_COUNT_EXCEEDED" },
	{ 0xC000004B, "STATUS_THREAD_IS_TERMINATING" },
	{ 0xC000004C, "STATUS_BAD_WORKING_SET_LIMIT" },
	{ 0xC000004D, "STATUS_INCOMPATIBLE_FILE_MAP" },
	{ 0xC000004E, "STATUS_SECTION_PROTECTION" },
	{ 0xC000004F, "STATUS_EAS_NOT_SUPPORTED" },
	{ 0xC0000050, "STATUS_EA_TOO_LARGE" },
	{ 0xC0000051, "STATUS_NONEXISTENT_EA_ENTRY" },
	{ 0xC0000052, "STATUS_NO_EAS_ON_FILE" },
	{ 0xC0000053, "STATUS_EA_CORRUPT_ERROR" },
	{ 0xC0000054, "STATUS_FILE_LOCK_CONFLICT" },
	{ 0xC0000055, "STATUS_LOCK_NOT_GRANTED" },
	{ 0xC0000056, "STATUS_DELETE_PENDING" },
	{ 0xC0000057, "STATUS_CTL_FILE_NOT_SUPPORTED" },
	{ 0xC0000058, "STATUS_UNKNOWN_REVISION" },
	{ 0xC0000059, "STATUS_REVISION_MISMATCH" },
	{ 0xC000005A, "STATUS_INVALID_OWNER" },
	{ 0xC000005B, "STATUS_INVALID_PRIMARY_GROUP" },
	{ 0xC000005C, "STATUS_NO_IMPERSONATION_TOKEN" },
	{ 0xC000005D, "STATUS_CANT_DISABLE_MANDATORY" },
	{ 0xC000005E, "STATUS_NO_LOGON_SERVERS" },
	{ 0xC000005F, "STATUS_NO_SUCH_LOGON_SESSION" },
	{ 0xC0000060, "STATUS_NO_SUCH_PRIVILEGE" },
	{ 0xC0000061, "STATUS_PRIVILEGE_NOT_HELD" },
	{ 0xC0000062, "STATUS_INVALID_ACCOUNT_NAME" },
	{ 0xC0000063, "STATUS_USER_EXISTS" },
	{ 0xC0000064, "STATUS_NO_SUCH_USER" },
	{ 0xC0000065, "STATUS_GROUP_EXISTS" },
	{ 0xC0000066, "STATUS_NO_SUCH_GROUP" },
	{ 0xC0000067, "STATUS_MEMBER_IN_GROUP" },
	{ 0xC0000068, "STATUS_MEMBER_NOT_IN_GROUP" },
	{ 0xC0000069, "STATUS_LAST_ADMIN" },
	{ 0xC000006A, "STATUS_WRONG_PASSWORD" },
	{ 0xC000006B, "STATUS_ILL_FORMED_PASSWORD" },
	{ 0xC000006C, "STATUS_PASSWORD_RESTRICTION" },
	{ 0xC000006D, "STATUS_LOGON_FAILURE" },
	{ 0xC000006E, "STATUS_ACCOUNT_RESTRICTION" },
	{ 0xC000006F, "STATUS_INVALID_LOGON_HOURS" },
	{ 0xC0000070, "STATUS_INVALID_WORKSTATION" },
	{ 0xC0000071, "STATUS_PASSWORD_EXPIRED" },
	{ 0xC0000072, "STATUS_ACCOUNT_DISABLED" },
	{ 0xC0000073, "STATUS_NONE_MAPPED" },
	{ 0xC0000074, "STATUS_TOO_MANY_LUIDS_REQUESTED" },
	{ 0xC0000075, "STATUS_LUIDS_EXHAUSTED" },
	{ 0xC0000076, "STATUS_INVALID_SUB_AUTHORITY" },
	{ 0xC0000077, "STATUS_INVALID_ACL" },
	{ 0xC0000078, "STATUS_INVALID_SID" },
	{ 0xC0000079, "STATUS_INVALID_SECURITY_DESCR" },
	{ 0xC000007A, "STATUS_PROCEDURE_NOT_FOUND" },
	{ 0xC000007B, "STATUS_INVALID_IMAGE_FORMAT" },
	{ 0xC000007C, "STATUS_NO_TOKEN" },
	{ 0xC000007D, "STATUS_BAD_INHERITANCE_ACL" },
	{ 0xC000007E, "STATUS_RANGE_NOT_LOCKED" },
	{ 0xC000007F, "STATUS_DISK_FULL" },
	{ 0xC0000080, "STATUS_SERVER_DISABLED" },
	{ 0xC0000081, "STATUS_SERVER_NOT_DISABLED" },
	{ 0xC0000082, "STATUS_TOO_MANY_GUIDS_REQUESTED" },
	{ 0xC0000083, "STATUS_GUIDS_EXHAUSTED" },
	{ 0xC0000084, "STATUS_INVALID_ID_AUTHORITY" },
	{ 0xC0000085, "STATUS_AGENTS_EXHAUSTED" },
	{ 0xC0000086, "STATUS_INVALID_VOLUME_LABEL" },
	{ 0xC0000087, "STATUS_SECTION_NOT_EXTENDED" },
	{ 0xC0000088, "STATUS_NOT_MAPPED_DATA" },
	{ 0xC0000089, "STATUS_RESOURCE_DATA_NOT_FOUND" },
	{ 0xC000008A, "STATUS_RESOURCE_TYPE_NOT_FOUND" },
	{ 0xC000008B, "STATUS_RESOURCE_NAME_NOT_FOUND" },
	{ 0xC000008C, "STATUS_ARRAY_BOUNDS_EXCEEDED" },
	{ 0xC000008D, "STATUS_FLOAT_DENORMAL_OPERAND" },
	{ 0xC000008E, "STATUS_FLOAT_DIVIDE_BY_ZERO" },
	{ 0xC000008F, "STATUS_FLOAT_INEXACT_RESULT" },
	{ 0xC0000090, "STATUS_FLOAT_INVALID_OPERATION" },
	{ 0xC0000091, "STATUS_FLOAT_OVERFLOW" },
	{ 0xC0000092, "STATUS_FLOAT_STACK_CHECK" },
	{ 0xC0000093, "STATUS_FLOAT_UNDERFLOW" },
	{ 0xC0000094, "STATUS_INTEGER_DIVIDE_BY_ZERO" },
	{ 0xC0000095, "STATUS_INTEGER_OVERFLOW" },
	{ 0xC0000096, "STATUS_PRIVILEGED_INSTRUCTION" },
	{ 0xC0000097, "STATUS_TOO_MANY_PAGING_FILES" },
	{ 0xC0000098, "STATUS_FILE_INVALID" },
	{ 0xC0000099, "STATUS_ALLOTTED_SPACE_EXCEEDED" },
	{ 0xC000009A, "STATUS_INSUFFICIENT_RESOURCES" },
	{ 0xC000009B, "STATUS_DFS_EXIT_PATH_FOUND" },
	{ 0xC000009C, "STATUS_DEVICE_DATA_ERROR" },
	{ 0xC000009D, "STATUS_DEVICE_NOT_CONNECTED" },
	{ 0xC000009E, "STATUS_DEVICE_POWER_FAILURE" },
	{ 0xC000009F, "STATUS_FREE_VM_NOT_AT_BASE" },
	{ 0xC00000A0, "STATUS_MEMORY_NOT_ALLOCATED" },
	{ 0xC00000A1, "STATUS_WORKING_SET_QUOTA" },
	{ 0xC00000A2, "STATUS_MEDIA_WRITE_PROTECTED" },
	{ 0xC00000A3, "STATUS_DEVICE_NOT_READY" },
	{ 0xC00000A4, "STATUS_INVALID_GROUP_ATTRIBUTES" },
	{ 0xC00000A5, "STATUS_BAD_IMPERSONATION_LEVEL" },
	{ 0xC00000A6, "STATUS_CANT_OPEN_ANONYMOUS" },
	{ 0xC00000A7, "STATUS_BAD_VALIDATION_CLASS" },
	{ 0xC00000A8, "STATUS_BAD_TOKEN_TYPE" },
	{ 0xC00000A9, "STATUS_BAD_MASTER_BOOT_RECORD" },
	{ 0xC00000AA, "STATUS_INSTRUCTION_MISALIGNMENT" },
	{ 0xC00000AB, "STATUS_INSTANCE_NOT_AVAILABLE" },
	{ 0xC00000AC, "STATUS_PIPE_NOT_AVAILABLE" },
	{ 0xC00000AD, "STATUS_INVALID_PIPE_STATE" },
	{ 0xC00000AE, "STATUS_PIPE_BUSY" },
	{ 0xC00000AF, "STATUS_ILLEGAL_FUNCTION" },
	{ 0xC00000B0, "STATUS_PIPE_DISCONNECTED" },
	{ 0xC00000B1, "STATUS_PIPE_CLOSING" },
	{ 0xC00000B2, "STATUS_PIPE_CONNECTED" },
	{ 0xC00000B3, "STATUS_PIPE_LISTENING" },
	{ 0xC00000B4, "STATUS_INVALID_READ_MODE" },
	{ 0xC00000B5, "STATUS_IO_TIMEOUT" },
	{ 0xC00000B6, "STATUS_FILE_FORCED_CLOSED" },
	{ 0xC00000B7, "STATUS_PROFILING_NOT_STARTED" },
	{ 0xC00000B8, "STATUS_PROFILING_NOT_STOPPED" },
	{ 0xC00000B9, "STATUS_COULD_NOT_INTERPRET" },
	{ 0xC00000BA, "STATUS_FILE_IS_A_DIRECTORY" },
	{ 0xC00000BB, "STATUS_NOT_SUPPORTED" },
	{ 0xC00000BC, "STATUS_REMOTE_NOT_LISTENING" },
	{ 0xC00000BD, "STATUS_DUPLICATE_NAME" },
	{ 0xC00000BE, "STATUS_BAD_NETWORK_PATH" },
	{ 0xC00000BF, "STATUS_NETWORK_BUSY" },
	{ 0xC00000C0, "STATUS_DEVICE_DOES_NOT_EXIST" },
	{ 0xC00000C1, "STATUS_TOO_MANY_COMMANDS" },
	{ 0xC00000C2, "STATUS_ADAPTER_HARDWARE_ERROR" },
	{ 0xC00000C3, "STATUS_INVALID_NETWORK_RESPONSE" },
	{ 0xC00000C4, "STATUS_UNEXPECTED_NETWORK_ERROR" },
	{ 0xC00000C5, "STATUS_BAD_REMOTE_ADAPTER" },
	{ 0xC00000C6, "STATUS_PRINT_QUEUE_FULL" },
	{ 0xC00000C7, "STATUS_NO_SPOOL_SPACE" },
	{ 0xC00000C8, "STATUS_PRINT_CANCELLED" },
	{ 0xC00000C9, "STATUS_NETWORK_NAME_DELETED" },
	{ 0xC00000CA, "STATUS_NETWORK_ACCESS_DENIED" },
	{ 0xC00000CB, "STATUS_BAD_DEVICE_TYPE" },
	{ 0xC00000CC, "STATUS_BAD_NETWORK_NAME" },
	{ 0xC00000CD, "STATUS_TOO_MANY_NAMES" },
	{ 0xC00000CE, "STATUS_TOO_MANY_SESSIONS" },
	{ 0xC00000CF, "STATUS_SHARING_PAUSED" },
	{ 0xC00000D0, "STATUS_REQUEST_NOT_ACCEPTED" },
	{ 0xC00000D1, "STATUS_REDIRECTOR_PAUSED" },
	{ 0xC00000D2, "STATUS_NET_WRITE_FAULT" },
	{ 0xC00000D3, "STATUS_PROFILING_AT_LIMIT" },
	{ 0xC00000D4, "STATUS_NOT_SAME_DEVICE" },
	{ 0xC00000D5, "STATUS_FILE_RENAMED" },
	{ 0xC00000D6, "STATUS_VIRTUAL_CIRCUIT_CLOSED" },
	{ 0xC00000D7, "STATUS_NO_SECURITY_ON_OBJECT" },
	{ 0xC00000D8, "STATUS_CANT_WAIT" },
	{ 0xC00000D9, "STATUS_PIPE_EMPTY" },
	{ 0xC00000DA, "STATUS_CANT_ACCESS_DOMAIN_INFO" },
	{ 0xC00000DB, "STATUS_CANT_TERMINATE_SELF" },
	{ 0xC00000DC, "STATUS_INVALID_SERVER_STATE" },
	{ 0xC00000DD, "STATUS_INVALID_DOMAIN_STATE" },
	{ 0xC00000DE, "STATUS_INVALID_DOMAIN_ROLE" },
	{ 0xC00000DF, "STATUS_NO_SUCH_DOMAIN" },
	{ 0xC00000E0, "STATUS_DOMAIN_EXISTS" },
	{ 0xC00000E1, "STATUS_DOMAIN_LIMIT_EXCEEDED" },
	{ 0xC00000E2, "STATUS_OPLOCK_NOT_GRANTED" },
	{ 0xC00000E3, "STATUS_INVALID_OPLOCK_PROTOCOL" },
	{ 0xC00000E4, "STATUS_INTERNAL_DB_CORRUPTION" },
	{ 0xC00000E5, "STATUS_INTERNAL_ERROR" },
	{ 0xC00000E6, "STATUS_GENERIC_NOT_MAPPED" },
	{ 0xC00000E7, "STATUS_BAD_DESCRIPTOR_FORMAT" },
	{ 0xC00000E8, "STATUS_INVALID_USER_BUFFER" },
	{ 0xC00000E9, "STATUS_UNEXPECTED_IO_ERROR" },
	{ 0xC00000EA, "STATUS_UNEXPECTED_MM_CREATE_ERR" },
	{ 0xC00000EB, "STATUS_UNEXPECTED_MM_MAP_ERROR" },
	{ 0xC00000EC, "STATUS_UNEXPECTED_MM_EXTEND_ERR" },
	{ 0xC00000ED, "STATUS_NOT_LOGON_PROCESS" },
	{ 0xC00000EE, "STATUS_LOGON_SESSION_EXISTS" },
	{ 0xC00000EF, "STATUS_INVALID_PARAMETER_1" },
	{ 0xC00000F0, "STATUS_INVALID_PARAMETER_2" },
	{ 0xC00000F1, "STATUS_INVALID_PARAMETER_3" },
	{ 0xC00000F2, "STATUS_INVALID_PARAMETER_4" },
	{ 0xC00000F3, "STATUS_INVALID_PARAMETER_5" },
	{ 0xC00000F4, "STATUS_INVALID_PARAMETER_6" },
	{ 0xC00000F5, "STATUS_INVALID_PARAMETER_7" },
	{ 0xC00000F6, "STATUS_INVALID_PARAMETER_8" },
	{ 0xC00000F7, "STATUS_INVALID_PARAMETER_9" },
	{ 0xC00000F8, "STATUS_INVALID_PARAMETER_10" },
	{ 0xC00000F9, "STATUS_INVALID_PARAMETER_11" },
	{ 0xC00000FA, "STATUS_INVALID_PARAMETER_12" },
	{ 0xC00000FB, "STATUS_REDIRECTOR_NOT_STARTED" },
	{ 0xC00000FC, "STATUS_REDIRECTOR_STARTED" },
	{ 0xC00000FD, "STATUS_STACK_OVERFLOW" },
	{ 0xC00000FE, "STATUS_NO_SUCH_PACKAGE" },
	{ 0xC00000FF, "STATUS_BAD_FUNCTION_TABLE" },
	{ 0xC0000100, "STATUS_VARIABLE_NOT_FOUND" },
	{ 0xC0000101, "STATUS_DIRECTORY_NOT_EMPTY" },
	{ 0xC0000102, "STATUS_FILE_CORRUPT_ERROR" },
	{ 0xC0000103, "STATUS_NOT_A_DIRECTORY" },
	{ 0xC0000104, "STATUS_BAD_LOGON_SESSION_STATE" },
	{ 0xC0000105, "STATUS_LOGON_SESSION_COLLISION" },
	{ 0xC0000106, "STATUS_NAME_TOO_LONG" },
	{ 0xC0000107, "STATUS_FILES_OPEN" },
	{ 0xC0000108, "STATUS_CONNECTION_IN_USE" },
	{ 0xC0000109, "STATUS_MESSAGE_NOT_FOUND" },
	{ 0xC000010A, "STATUS_PROCESS_IS_TERMINATING" },
	{ 0xC000010B, "STATUS_INVALID_LOGON_TYPE" },
	{ 0xC000010C, "STATUS_NO_GUID_TRANSLATION" },
	{ 0xC000010D, "STATUS_CANNOT_IMPERSONATE" },
	{ 0xC000010E, "STATUS_IMAGE_ALREADY_LOADED" },
	{ 0xC000010F, "STATUS_ABIOS_NOT_PRESENT" },
	{ 0xC0000110, "STATUS_ABIOS_LID_NOT_EXIST" },
	{ 0xC0000111, "STATUS_ABIOS_LID_ALREADY_OWNED" },
	{ 0xC0000112, "STATUS_ABIOS_NOT_LID_OWNER" },
	{ 0xC0000113, "STATUS_ABIOS_INVALID_COMMAND" },
	{ 0xC0000114, "STATUS_ABIOS_INVALID_LID" },
	{ 0xC0000115, "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE" },
	{ 0xC0000116, "STATUS_ABIOS_INVALID_SELECTOR" },
	{ 0xC0000117, "STATUS_NO_LDT" },
	{ 0xC0000118, "STATUS_INVALID_LDT_SIZE" },
	{ 0xC0000119, "STATUS_INVALID_LDT_OFFSET" },
	{ 0xC000011A, "STATUS_INVALID_LDT_DESCRIPTOR" },
	{ 0xC000011B, "STATUS_INVALID_IMAGE_NE_FORMAT" },
	{ 0xC000011C, "STATUS_RXACT_INVALID_STATE" },
	{ 0xC000011D, "STATUS_RXACT_COMMIT_FAILURE" },
	{ 0xC000011E, "STATUS_MAPPED_FILE_SIZE_ZERO" },
	{ 0xC000011F, "STATUS_TOO_MANY_OPENED_FILES" },
	{ 0xC0000120, "STATUS_CANCELLED" },
	{ 0xC0000121, "STATUS_CANNOT_DELETE" },
	{ 0xC0000122, "STATUS_INVALID_COMPUTER_NAME" },
	{ 0xC0000123, "STATUS_FILE_DELETED" },
	{ 0xC0000124, "STATUS_SPECIAL_ACCOUNT" },
	{ 0xC0000125, "STATUS_SPECIAL_GROUP" },
	{ 0xC0000126, "STATUS_SPECIAL_USER" },
	{ 0xC0000127, "STATUS_MEMBERS_PRIMARY_GROUP" },
	{ 0xC0000128, "STATUS_FILE_CLOSED" },
	{ 0xC0000129, "STATUS_TOO_MANY_THREADS" },
	{ 0xC000012A, "STATUS_THREAD_NOT_IN_PROCESS" },
	{ 0xC000012B, "STATUS_TOKEN_ALREADY_IN_USE" },
	{ 0xC000012C, "STATUS_PAGEFILE_QUOTA_EXCEEDED" },
	{ 0xC000012D, "STATUS_COMMITMENT_LIMIT" },
	{ 0xC000012E, "STATUS_INVALID_IMAGE_LE_FORMAT" },
	{ 0xC000012F, "STATUS_INVALID_IMAGE_NOT_MZ" },
	{ 0xC0000130, "STATUS_INVALID_IMAGE_PROTECT" },
	{ 0xC0000131, "STATUS_INVALID_IMAGE_WIN_16" },
	{ 0xC0000132, "STATUS_LOGON_SERVER_CONFLICT" },
	{ 0xC0000133, "STATUS_TIME_DIFFERENCE_AT_DC" },
	{ 0xC0000134, "STATUS_SYNCHRONIZATION_REQUIRED" },
	{ 0xC0000135, "STATUS_DLL_NOT_FOUND" },
	{ 0xC0000136, "STATUS_OPEN_FAILED" },
	{ 0xC0000137, "STATUS_IO_PRIVILEGE_FAILED" },
	{ 0xC0000138, "STATUS_ORDINAL_NOT_FOUND" },
	{ 0xC0000139, "STATUS_ENTRYPOINT_NOT_FOUND" },
	{ 0xC000013A, "STATUS_CONTROL_C_EXIT" },
	{ 0xC000013B, "STATUS_LOCAL_DISCONNECT" },
	{ 0xC000013C, "STATUS_REMOTE_DISCONNECT" },
	{ 0xC000013D, "STATUS_REMOTE_RESOURCES" },
	{ 0xC000013E, "STATUS_LINK_FAILED" },
	{ 0xC000013F, "STATUS_LINK_TIMEOUT" },
	{ 0xC0000140, "STATUS_INVALID_CONNECTION" },
	{ 0xC0000141, "STATUS_INVALID_ADDRESS" },
	{ 0xC0000142, "STATUS_DLL_INIT_FAILED" },
	{ 0xC0000143, "STATUS_MISSING_SYSTEMFILE" },
	{ 0xC0000144, "STATUS_UNHANDLED_EXCEPTION" },
	{ 0xC0000145, "STATUS_APP_INIT_FAILURE" },
	{ 0xC0000146, "STATUS_PAGEFILE_CREATE_FAILED" },
	{ 0xC0000147, "STATUS_NO_PAGEFILE" },
	{ 0xC0000148, "STATUS_INVALID_LEVEL" },
	{ 0xC0000149, "STATUS_WRONG_PASSWORD_CORE" },
	{ 0xC000014A, "STATUS_ILLEGAL_FLOAT_CONTEXT" },
	{ 0xC000014B, "STATUS_PIPE_BROKEN" },
	{ 0xC000014C, "STATUS_REGISTRY_CORRUPT" },
	{ 0xC000014D, "STATUS_REGISTRY_IO_FAILED" },
	{ 0xC000014E, "STATUS_NO_EVENT_PAIR" },
	{ 0xC000014F, "STATUS_UNRECOGNIZED_VOLUME" },
	{ 0xC0000150, "STATUS_SERIAL_NO_DEVICE_INITED" },
	{ 0xC0000151, "STATUS_NO_SUCH_ALIAS" },
	{ 0xC0000152, "STATUS_MEMBER_NOT_IN_ALIAS" },
	{ 0xC0000153, "STATUS_MEMBER_IN_ALIAS" },
	{ 0xC0000154, "STATUS_ALIAS_EXISTS" },
	{ 0xC0000155, "STATUS_LOGON_NOT_GRANTED" },
	{ 0xC0000156, "STATUS_TOO_MANY_SECRETS" },
	{ 0xC0000157, "STATUS_SECRET_TOO_LONG" },
	{ 0xC0000158, "STATUS_INTERNAL_DB_ERROR" },
	{ 0xC0000159, "STATUS_FULLSCREEN_MODE" },
	{ 0xC000015A, "STATUS_TOO_MANY_CONTEXT_IDS" },
	{ 0xC000015B, "STATUS_LOGON_TYPE_NOT_GRANTED" },
	{ 0xC000015C, "STATUS_NOT_REGISTRY_FILE" },
	{ 0xC000015D, "STATUS_NT_CROSS_ENCRYPTION_REQUIRED" },
	{ 0xC000015E, "STATUS_DOMAIN_CTRLR_CONFIG_ERROR" },
	{ 0xC000015F, "STATUS_FT_MISSING_MEMBER" },
	{ 0xC0000160, "STATUS_ILL_FORMED_SERVICE_ENTRY" },
	{ 0xC0000161, "STATUS_ILLEGAL_CHARACTER" },
	{ 0xC0000162, "STATUS_UNMAPPABLE_CHARACTER" },
	{ 0xC0000163, "STATUS_UNDEFINED_CHARACTER" },
	{ 0xC0000164, "STATUS_FLOPPY_VOLUME" },
	{ 0xC0000165, "STATUS_FLOPPY_ID_MARK_NOT_FOUND" },
	{ 0xC0000166, "STATUS_FLOPPY_WRONG_CYLINDER" },
	{ 0xC0000167, "STATUS_FLOPPY_UNKNOWN_ERROR" },
	{ 0xC0000168, "STATUS_FLOPPY_BAD_REGISTERS" },
	{ 0xC0000169, "STATUS_DISK_RECALIBRATE_FAILED" },
	{ 0xC000016A, "STATUS_DISK_OPERATION_FAILED" },
	{ 0xC000016B, "STATUS_DISK_RESET_FAILED" },
	{ 0xC000016C, "STATUS_SHARED_IRQ_BUSY" },
	{ 0xC000016D, "STATUS_FT_ORPHANING" },
	{ 0xC000016E, "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT" },
	{ 0xC0000172, "STATUS_PARTITION_FAILURE" },
	{ 0xC0000173, "STATUS_INVALID_BLOCK_LENGTH" },
	{ 0xC0000174, "STATUS_DEVICE_NOT_PARTITIONED" },
	{ 0xC0000175, "STATUS_UNABLE_TO_LOCK_MEDIA" },
	{ 0xC0000176, "STATUS_UNABLE_TO_UNLOAD_MEDIA" },
	{ 0xC0000177, "STATUS_EOM_OVERFLOW" },
	{ 0xC0000178, "STATUS_NO_MEDIA" },
	{ 0xC000017A, "STATUS_NO_SUCH_MEMBER" },
	{ 0xC000017B, "STATUS_INVALID_MEMBER" },
	{ 0xC000017C, "STATUS_KEY_DELETED" },
	{ 0xC000017D, "STATUS_NO_LOG_SPACE" },
	{ 0xC000017E, "STATUS_TOO_MANY_SIDS" },
	{ 0xC000017F, "STATUS_LM_CROSS_ENCRYPTION_REQUIRED" },
	{ 0xC0000180, "STATUS_KEY_HAS_CHILDREN" },
	{ 0xC0000181, "STATUS_CHILD_MUST_BE_VOLATILE" },
	{ 0xC0000182, "STATUS_DEVICE_CONFIGURATION_ERROR" },
	{ 0xC0000183, "STATUS_DRIVER_INTERNAL_ERROR" },
	{ 0xC0000184, "STATUS_INVALID_DEVICE_STATE" },
	{ 0xC0000185, "STATUS_IO_DEVICE_ERROR" },
	{ 0xC0000186, "STATUS_DEVICE_PROTOCOL_ERROR" },
	{ 0xC0000187, "STATUS_BACKUP_CONTROLLER" },
	{ 0xC0000188, "STATUS_LOG_FILE_FULL" },
	{ 0xC0000189, "STATUS_TOO_LATE" },
	{ 0xC000018A, "STATUS_NO_TRUST_LSA_SECRET" },
	{ 0xC000018B, "STATUS_NO_TRUST_SAM_ACCOUNT" },
	{ 0xC000018C, "STATUS_TRUSTED_DOMAIN_FAILURE" },
	{ 0xC000018D, "STATUS_TRUSTED_RELATIONSHIP_FAILURE" },
	{ 0xC000018E, "STATUS_EVENTLOG_FILE_CORRUPT" },
	{ 0xC000018F, "STATUS_EVENTLOG_CANT_START" },
	{ 0xC0000190, "STATUS_TRUST_FAILURE" },
	{ 0xC0000191, "STATUS_MUTANT_LIMIT_EXCEEDED" },
	{ 0xC0000192, "STATUS_NETLOGON_NOT_STARTED" },
	{ 0xC0000193, "STATUS_ACCOUNT_EXPIRED" },
	{ 0xC0000194, "STATUS_POSSIBLE_DEADLOCK" },
	{ 0xC0000195, "STATUS_NETWORK_CREDENTIAL_CONFLICT" },
	{ 0xC0000196, "STATUS_REMOTE_SESSION_LIMIT" },
	{ 0xC0000197, "STATUS_EVENTLOG_FILE_CHANGED" },
	{ 0xC0000198, "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT" },
	{ 0xC0000199, "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT" },
	{ 0xC000019A, "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT" },
	{ 0xC000019B, "STATUS_DOMAIN_TRUST_INCONSISTENT" },
	{ 0xC000019C, "STATUS_FS_DRIVER_REQUIRED" },
	{ 0xC0000202, "STATUS_NO_USER_SESSION_KEY" },
	{ 0xC0000203, "STATUS_USER_SESSION_DELETED" },
	{ 0xC0000204, "STATUS_RESOURCE_LANG_NOT_FOUND" },
	{ 0xC0000205, "STATUS_INSUFF_SERVER_RESOURCES" },
	{ 0xC0000206, "STATUS_INVALID_BUFFER_SIZE" },
	{ 0xC0000207, "STATUS_INVALID_ADDRESS_COMPONENT" },
	{ 0xC0000208, "STATUS_INVALID_ADDRESS_WILDCARD" },
	{ 0xC0000209, "STATUS_TOO_MANY_ADDRESSES" },
	{ 0xC000020A, "STATUS_ADDRESS_ALREADY_EXISTS" },
	{ 0xC000020B, "STATUS_ADDRESS_CLOSED" },
	{ 0xC000020C, "STATUS_CONNECTION_DISCONNECTED" },
	{ 0xC000020D, "STATUS_CONNECTION_RESET" },
	{ 0xC000020E, "STATUS_TOO_MANY_NODES" },
	{ 0xC000020F, "STATUS_TRANSACTION_ABORTED" },
	{ 0xC0000210, "STATUS_TRANSACTION_TIMED_OUT" },
	{ 0xC0000211, "STATUS_TRANSACTION_NO_RELEASE" },
	{ 0xC0000212, "STATUS_TRANSACTION_NO_MATCH" },
	{ 0xC0000213, "STATUS_TRANSACTION_RESPONDED" },
	{ 0xC0000214, "STATUS_TRANSACTION_INVALID_ID" },
	{ 0xC0000215, "STATUS_TRANSACTION_INVALID_TYPE" },
	{ 0xC0000216, "STATUS_NOT_SERVER_SESSION" },
	{ 0xC0000217, "STATUS_NOT_CLIENT_SESSION" },
	{ 0xC0000218, "STATUS_CANNOT_LOAD_REGISTRY_FILE" },
	{ 0xC0000219, "STATUS_DEBUG_ATTACH_FAILED" },
	{ 0xC000021A, "STATUS_SYSTEM_PROCESS_TERMINATED" },
	{ 0xC000021B, "STATUS_DATA_NOT_ACCEPTED" },
	{ 0xC000021C, "STATUS_NO_BROWSER_SERVERS_FOUND" },
	{ 0xC000021D, "STATUS_VDM_HARD_ERROR" },
	{ 0xC000021E, "STATUS_DRIVER_CANCEL_TIMEOUT" },
	{ 0xC000021F, "STATUS_REPLY_MESSAGE_MISMATCH" },
	{ 0xC0000220, "STATUS_MAPPED_ALIGNMENT" },
	{ 0xC0000221, "STATUS_IMAGE_CHECKSUM_MISMATCH" },
	{ 0xC0000222, "STATUS_LOST_WRITEBEHIND_DATA" },
	{ 0xC0000223, "STATUS_CLIENT_SERVER_PARAMETERS_INVALID" },
	{ 0xC0000224, "STATUS_PASSWORD_MUST_CHANGE" },
	{ 0xC0000225, "STATUS_NOT_FOUND" },
	{ 0xC0000226, "STATUS_NOT_TINY_STREAM" },
	{ 0xC0000227, "STATUS_RECOVERY_FAILURE" },
	{ 0xC0000228, "STATUS_STACK_OVERFLOW_READ" },
	{ 0xC0000229, "STATUS_FAIL_CHECK" },
	{ 0xC000022A, "STATUS_DUPLICATE_OBJECTID" },
	{ 0xC000022B, "STATUS_OBJECTID_EXISTS" },
	{ 0xC000022C, "STATUS_CONVERT_TO_LARGE" },
	{ 0xC000022D, "STATUS_RETRY" },
	{ 0xC000022E, "STATUS_FOUND_OUT_OF_SCOPE" },
	{ 0xC000022F, "STATUS_ALLOCATE_BUCKET" },
	{ 0xC0000230, "STATUS_PROPSET_NOT_FOUND" },
	{ 0xC0000231, "STATUS_MARSHALL_OVERFLOW" },
	{ 0xC0000232, "STATUS_INVALID_VARIANT" },
	{ 0xC0000233, "STATUS_DOMAIN_CONTROLLER_NOT_FOUND" },
	{ 0xC0000234, "STATUS_ACCOUNT_LOCKED_OUT" },
	{ 0xC0000235, "STATUS_HANDLE_NOT_CLOSABLE" },
	{ 0xC0000236, "STATUS_CONNECTION_REFUSED" },
	{ 0xC0000237, "STATUS_GRACEFUL_DISCONNECT" },
	{ 0xC0000238, "STATUS_ADDRESS_ALREADY_ASSOCIATED" },
	{ 0xC0000239, "STATUS_ADDRESS_NOT_ASSOCIATED" },
	{ 0xC000023A, "STATUS_CONNECTION_INVALID" },
	{ 0xC000023B, "STATUS_CONNECTION_ACTIVE" },
	{ 0xC000023C, "STATUS_NETWORK_UNREACHABLE" },
	{ 0xC000023D, "STATUS_HOST_UNREACHABLE" },
	{ 0xC000023E, "STATUS_PROTOCOL_UNREACHABLE" },
	{ 0xC000023F, "STATUS_PORT_UNREACHABLE" },
	{ 0xC0000240, "STATUS_REQUEST_ABORTED" },
	{ 0xC0000241, "STATUS_CONNECTION_ABORTED" },
	{ 0xC0000242, "STATUS_BAD_COMPRESSION_BUFFER" },
	{ 0xC0000243, "STATUS_USER_MAPPED_FILE" },
	{ 0xC0000244, "STATUS_AUDIT_FAILED" },
	{ 0xC0000245, "STATUS_TIMER_RESOLUTION_NOT_SET" },
	{ 0xC0000246, "STATUS_CONNECTION_COUNT_LIMIT" },
	{ 0xC0000247, "STATUS_LOGIN_TIME_RESTRICTION" },
	{ 0xC0000248, "STATUS_LOGIN_WKSTA_RESTRICTION" },
	{ 0xC0000249, "STATUS_IMAGE_MP_UP_MISMATCH" },
	{ 0xC0000250, "STATUS_INSUFFICIENT_LOGON_INFO" },
	{ 0xC0000251, "STATUS_BAD_DLL_ENTRYPOINT" },
	{ 0xC0000252, "STATUS_BAD_SERVICE_ENTRYPOINT" },
	{ 0xC0000253, "STATUS_LPC_REPLY_LOST" },
	{ 0xC0000254, "STATUS_IP_ADDRESS_CONFLICT1" },
	{ 0xC0000255, "STATUS_IP_ADDRESS_CONFLICT2" },
	{ 0xC0000256, "STATUS_REGISTRY_QUOTA_LIMIT" },
	{ 0xC0000257, "STATUS_PATH_NOT_COVERED" },
	{ 0xC0000258, "STATUS_NO_CALLBACK_ACTIVE" },
	{ 0xC0000259, "STATUS_LICENSE_QUOTA_EXCEEDED" },
	{ 0xC000025A, "STATUS_PWD_TOO_SHORT" },
	{ 0xC000025B, "STATUS_PWD_TOO_RECENT" },
	{ 0xC000025C, "STATUS_PWD_HISTORY_CONFLICT" },
	{ 0xC000025E, "STATUS_PLUGPLAY_NO_DEVICE" },
	{ 0xC000025F, "STATUS_UNSUPPORTED_COMPRESSION" },
	{ 0xC0000260, "STATUS_INVALID_HW_PROFILE" },
	{ 0xC0000261, "STATUS_INVALID_PLUGPLAY_DEVICE_PATH" },
	{ 0xC0000262, "STATUS_DRIVER_ORDINAL_NOT_FOUND" },
	{ 0xC0000263, "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND" },
	{ 0xC0000264, "STATUS_RESOURCE_NOT_OWNED" },
	{ 0xC0000265, "STATUS_TOO_MANY_LINKS" },
	{ 0xC0000266, "STATUS_QUOTA_LIST_INCONSISTENT" },
	{ 0xC0000267, "STATUS_FILE_IS_OFFLINE" },
	{ 0xC0000268, "STATUS_EVALUATION_EXPIRATION" },
	{ 0xC0000269, "STATUS_ILLEGAL_DLL_RELOCATION" },
	{ 0xC000026A, "STATUS_LICENSE_VIOLATION" },
	{ 0xC000026B, "STATUS_DLL_INIT_FAILED_LOGOFF" },
	{ 0xC000026C, "STATUS_DRIVER_UNABLE_TO_LOAD" },
	{ 0xC000026D, "STATUS_DFS_UNAVAILABLE" },
	{ 0xC000026E, "STATUS_VOLUME_DISMOUNTED" },
	{ 0xC000026F, "STATUS_WX86_INTERNAL_ERROR" },
	{ 0xC0000270, "STATUS_WX86_FLOAT_STACK_CHECK" },
	{ 0xC0000271, "STATUS_VALIDATE_CONTINUE" },
	{ 0xC0000272, "STATUS_NO_MATCH" },
	{ 0xC0000273, "STATUS_NO_MORE_MATCHES" },
	{ 0xC0000275, "STATUS_NOT_A_REPARSE_POINT" },
	{ 0xC0000276, "STATUS_IO_REPARSE_TAG_INVALID" },
	{ 0xC0000277, "STATUS_IO_REPARSE_TAG_MISMATCH" },
	{ 0xC0000278, "STATUS_IO_REPARSE_DATA_INVALID" },
	{ 0xC0000279, "STATUS_IO_REPARSE_TAG_NOT_HANDLED" },
	{ 0xC0000280, "STATUS_REPARSE_POINT_NOT_RESOLVED" },
	{ 0xC0000281, "STATUS_DIRECTORY_IS_A_REPARSE_POINT" },
	{ 0xC0000282, "STATUS_RANGE_LIST_CONFLICT" },
	{ 0xC0000283, "STATUS_SOURCE_ELEMENT_EMPTY" },
	{ 0xC0000284, "STATUS_DESTINATION_ELEMENT_FULL" },
	{ 0xC0000285, "STATUS_ILLEGAL_ELEMENT_ADDRESS" },
	{ 0xC0000286, "STATUS_MAGAZINE_NOT_PRESENT" },
	{ 0xC0000287, "STATUS_REINITIALIZATION_NEEDED" },
	{ 0xC000028A, "STATUS_ENCRYPTION_FAILED" },
	{ 0xC000028B, "STATUS_DECRYPTION_FAILED" },
	{ 0xC000028C, "STATUS_RANGE_NOT_FOUND" },
	{ 0xC000028D, "STATUS_NO_RECOVERY_POLICY" },
	{ 0xC000028E, "STATUS_NO_EFS" },
	{ 0xC000028F, "STATUS_WRONG_EFS" },
	{ 0xC0000290, "STATUS_NO_USER_KEYS" },
	{ 0xC0000291, "STATUS_FILE_NOT_ENCRYPTED" },
	{ 0xC0000292, "STATUS_NOT_EXPORT_FORMAT" },
	{ 0xC0000293, "STATUS_FILE_ENCRYPTED" },
	{ 0xC0000295, "STATUS_WMI_GUID_NOT_FOUND" },
	{ 0xC0000296, "STATUS_WMI_INSTANCE_NOT_FOUND" },
	{ 0xC0000297, "STATUS_WMI_ITEMID_NOT_FOUND" },
	{ 0xC0000298, "STATUS_WMI_TRY_AGAIN" },
	{ 0xC0000299, "STATUS_SHARED_POLICY" },
	{ 0xC000029A, "STATUS_POLICY_OBJECT_NOT_FOUND" },
	{ 0xC000029B, "STATUS_POLICY_ONLY_IN_DS" },
	{ 0xC000029C, "STATUS_VOLUME_NOT_UPGRADED" },
	{ 0xC000029D, "STATUS_REMOTE_STORAGE_NOT_ACTIVE" },
	{ 0xC000029E, "STATUS_REMOTE_STORAGE_MEDIA_ERROR" },
	{ 0xC000029F, "STATUS_NO_TRACKING_SERVICE" },
	{ 0xC00002A0, "STATUS_SERVER_SID_MISMATCH" },
	{ 0xC00002A1, "STATUS_DS_NO_ATTRIBUTE_OR_VALUE" },
	{ 0xC00002A2, "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX" },
	{ 0xC00002A3, "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED" },
	{ 0xC00002A4, "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS" },
	{ 0xC00002A5, "STATUS_DS_BUSY" },
	{ 0xC00002A6, "STATUS_DS_UNAVAILABLE" },
	{ 0xC00002A7, "STATUS_DS_NO_RIDS_ALLOCATED" },
	{ 0xC00002A8, "STATUS_DS_NO_MORE_RIDS" },
	{ 0xC00002A9, "STATUS_DS_INCORRECT_ROLE_OWNER" },
	{ 0xC00002AA, "STATUS_DS_RIDMGR_INIT_ERROR" },
	{ 0xC00002AB, "STATUS_DS_OBJ_CLASS_VIOLATION" },
	{ 0xC00002AC, "STATUS_DS_CANT_ON_NON_LEAF" },
	{ 0xC00002AD, "STATUS_DS_CANT_ON_RDN" },
	{ 0xC00002AE, "STATUS_DS_CANT_MOD_OBJ_CLASS" },
	{ 0xC00002AF, "STATUS_DS_CROSS_DOM_MOVE_FAILED" },
	{ 0xC00002B0, "STATUS_DS_GC_NOT_AVAILABLE" },
	{ 0xC00002B1, "STATUS_DIRECTORY_SERVICE_REQUIRED" },
	{ 0xC00002B2, "STATUS_REPARSE_ATTRIBUTE_CONFLICT" },
	{ 0xC00002B3, "STATUS_CANT_ENABLE_DENY_ONLY" },
	{ 0xC00002B4, "STATUS_FLOAT_MULTIPLE_FAULTS" },
	{ 0xC00002B5, "STATUS_FLOAT_MULTIPLE_TRAPS" },
	{ 0xC00002B6, "STATUS_DEVICE_REMOVED" },
	{ 0xC00002B7, "STATUS_JOURNAL_DELETE_IN_PROGRESS" },
	{ 0xC00002B8, "STATUS_JOURNAL_NOT_ACTIVE" },
	{ 0xC00002B9, "STATUS_NOINTERFACE" },
	{ 0xC00002C1, "STATUS_DS_ADMIN_LIMIT_EXCEEDED" },
	{ 0xC00002C2, "STATUS_DRIVER_FAILED_SLEEP" },
	{ 0xC00002C3, "STATUS_MUTUAL_AUTHENTICATION_FAILED" },
	{ 0xC00002C4, "STATUS_CORRUPT_SYSTEM_FILE" },
	{ 0xC00002C5, "STATUS_DATATYPE_MISALIGNMENT_ERROR" },
	{ 0xC00002C6, "STATUS_WMI_READ_ONLY" },
	{ 0xC00002C7, "STATUS_WMI_SET_FAILURE" },
	{ 0xC00002C8, "STATUS_COMMITMENT_MINIMUM" },
	{ 0xC00002C9, "STATUS_REG_NAT_CONSUMPTION" },
	{ 0xC00002CA, "STATUS_TRANSPORT_FULL" },
	{ 0xC00002CB, "STATUS_DS_SAM_INIT_FAILURE" },
	{ 0xC00002CC, "STATUS_ONLY_IF_CONNECTED" },
	{ 0xC00002CD, "STATUS_DS_SENSITIVE_GROUP_VIOLATION" },
	{ 0xC00002CE, "STATUS_PNP_RESTART_ENUMERATION" },
	{ 0xC00002CF, "STATUS_JOURNAL_ENTRY_DELETED" },
	{ 0xC00002D0, "STATUS_DS_CANT_MOD_PRIMARYGROUPID" },
	{ 0xC00002D1, "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE" },
	{ 0xC00002D2, "STATUS_PNP_REBOOT_REQUIRED" },
	{ 0xC00002D3, "STATUS_POWER_STATE_INVALID" },
	{ 0xC00002D4, "STATUS_DS_INVALID_GROUP_TYPE" },
	{ 0xC00002D5, "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN" },
	{ 0xC00002D6, "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN" },
	{ 0xC00002D7, "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER" },
	{ 0xC00002D8, "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER" },
	{ 0xC00002D9, "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER" },
	{ 0xC00002DA, "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER" },
	{ 0xC00002DB, "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER" },
	{ 0xC00002DC, "STATUS_DS_HAVE_PRIMARY_MEMBERS" },
	{ 0xC00002DD, "STATUS_WMI_NOT_SUPPORTED" },
	{ 0xC00002DE, "STATUS_INSUFFICIENT_POWER" },
	{ 0xC00002DF, "STATUS_SAM_NEED_BOOTKEY_PASSWORD" },
	{ 0xC00002E0, "STATUS_SAM_NEED_BOOTKEY_FLOPPY" },
	{ 0xC00002E1, "STATUS_DS_CANT_START" },
	{ 0xC00002E2, "STATUS_DS_INIT_FAILURE" },
	{ 0xC00002E3, "STATUS_SAM_INIT_FAILURE" },
	{ 0xC00002E4, "STATUS_DS_GC_REQUIRED" },
	{ 0xC00002E5, "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY" },
	{ 0xC00002E6, "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS" },
	{ 0xC00002E7, "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED" },
	{ 0xC00002E8, "STATUS_MULTIPLE_FAULT_VIOLATION" },
	{ 0xC0000300, "STATUS_NOT_SUPPORTED_ON_SBS" },
	{ 0xC000035C, "STATUS_NETWORK_SESSION_EXPIRED" },
	{ 0xC0000463, "STATUS_DEVICE_FEATURE_NOT_SUPPORTED" },
	{ 0xC0000464, "STATUS_DEVICE_UNREACHABLE" },
	{ 0xC0000465, "STATUS_INVALID_TOKEN" },
	{ 0xC0009898, "STATUS_WOW_ASSERTION" },
	{ 0xC0020001, "RPC_NT_INVALID_STRING_BINDING" },
	{ 0xC0020002, "RPC_NT_WRONG_KIND_OF_BINDING" },
	{ 0xC0020003, "RPC_NT_INVALID_BINDING" },
	{ 0xC0020004, "RPC_NT_PROTSEQ_NOT_SUPPORTED" },
	{ 0xC0020005, "RPC_NT_INVALID_RPC_PROTSEQ" },
	{ 0xC0020006, "RPC_NT_INVALID_STRING_UUID" },
	{ 0xC0020007, "RPC_NT_INVALID_ENDPOINT_FORMAT" },
	{ 0xC0020008, "RPC_NT_INVALID_NET_ADDR" },
	{ 0xC0020009, "RPC_NT_NO_ENDPOINT_FOUND" },
	{ 0xC002000A, "RPC_NT_INVALID_TIMEOUT" },
	{ 0xC002000B, "RPC_NT_OBJECT_NOT_FOUND" },
	{ 0xC002000C, "RPC_NT_ALREADY_REGISTERED" },
	{ 0xC002000D, "RPC_NT_TYPE_ALREADY_REGISTERED" },
	{ 0xC002000E, "RPC_NT_ALREADY_LISTENING" },
	{ 0xC002000F, "RPC_NT_NO_PROTSEQS_REGISTERED" },
	{ 0xC0020010, "RPC_NT_NOT_LISTENING" },
	{ 0xC0020011, "RPC_NT_UNKNOWN_MGR_TYPE" },
	{ 0xC0020012, "RPC_NT_UNKNOWN_IF" },
	{ 0xC0020013, "RPC_NT_NO_BINDINGS" },
	{ 0xC0020014, "RPC_NT_NO_PROTSEQS" },
	{ 0xC0020015, "RPC_NT_CANT_CREATE_ENDPOINT" },
	{ 0xC0020016, "RPC_NT_OUT_OF_RESOURCES" },
	{ 0xC0020017, "RPC_NT_SERVER_UNAVAILABLE" },
	{ 0xC0020018, "RPC_NT_SERVER_TOO_BUSY" },
	{ 0xC0020019, "RPC_NT_INVALID_NETWORK_OPTIONS" },
	{ 0xC002001A, "RPC_NT_NO_CALL_ACTIVE" },
	{ 0xC002001B, "RPC_NT_CALL_FAILED" },
	{ 0xC002001C, "RPC_NT_CALL_FAILED_DNE" },
	{ 0xC002001D, "RPC_NT_PROTOCOL_ERROR" },
	{ 0xC002001F, "RPC_NT_UNSUPPORTED_TRANS_SYN" },
	{ 0xC0020021, "RPC_NT_UNSUPPORTED_TYPE" },
	{ 0xC0020022, "RPC_NT_INVALID_TAG" },
	{ 0xC0020023, "RPC_NT_INVALID_BOUND" },
	{ 0xC0020024, "RPC_NT_NO_ENTRY_NAME" },
	{ 0xC0020025, "RPC_NT_INVALID_NAME_SYNTAX" },
	{ 0xC0020026, "RPC_NT_UNSUPPORTED_NAME_SYNTAX" },
	{ 0xC0020028, "RPC_NT_UUID_NO_ADDRESS" },
	{ 0xC0020029, "RPC_NT_DUPLICATE_ENDPOINT" },
	{ 0xC002002A, "RPC_NT_UNKNOWN_AUTHN_TYPE" },
	{ 0xC002002B, "RPC_NT_MAX_CALLS_TOO_SMALL" },
	{ 0xC002002C, "RPC_NT_STRING_TOO_LONG" },
	{ 0xC002002D, "RPC_NT_PROTSEQ_NOT_FOUND" },
	{ 0xC002002E, "RPC_NT_PROCNUM_OUT_OF_RANGE" },
	{ 0xC002002F, "RPC_NT_BINDING_HAS_NO_AUTH" },
	{ 0xC0020030, "RPC_NT_UNKNOWN_AUTHN_SERVICE" },
	{ 0xC0020031, "RPC_NT_UNKNOWN_AUTHN_LEVEL" },
	{ 0xC0020032, "RPC_NT_INVALID_AUTH_IDENTITY" },
	{ 0xC0020033, "RPC_NT_UNKNOWN_AUTHZ_SERVICE" },
	{ 0xC0020034, "EPT_NT_INVALID_ENTRY" },
	{ 0xC0020035, "EPT_NT_CANT_PERFORM_OP" },
	{ 0xC0020036, "EPT_NT_NOT_REGISTERED" },
	{ 0xC0020037, "RPC_NT_NOTHING_TO_EXPORT" },
	{ 0xC0020038, "RPC_NT_INCOMPLETE_NAME" },
	{ 0xC0020039, "RPC_NT_INVALID_VERS_OPTION" },
	{ 0xC002003A, "RPC_NT_NO_MORE_MEMBERS" },
	{ 0xC002003B, "RPC_NT_NOT_ALL_OBJS_UNEXPORTED" },
	{ 0xC002003C, "RPC_NT_INTERFACE_NOT_FOUND" },
	{ 0xC002003D, "RPC_NT_ENTRY_ALREADY_EXISTS" },
	{ 0xC002003E, "RPC_NT_ENTRY_NOT_FOUND" },
	{ 0xC002003F, "RPC_NT_NAME_SERVICE_UNAVAILABLE" },
	{ 0xC0020040, "RPC_NT_INVALID_NAF_ID" },
	{ 0xC0020041, "RPC_NT_CANNOT_SUPPORT" },
	{ 0xC0020042, "RPC_NT_NO_CONTEXT_AVAILABLE" },
	{ 0xC0020043, "RPC_NT_INTERNAL_ERROR" },
	{ 0xC0020044, "RPC_NT_ZERO_DIVIDE" },
	{ 0xC0020045, "RPC_NT_ADDRESS_ERROR" },
	{ 0xC0020046, "RPC_NT_FP_DIV_ZERO" },
	{ 0xC0020047, "RPC_NT_FP_UNDERFLOW" },
	{ 0xC0020048, "RPC_NT_FP_OVERFLOW" },
	{ 0xC0020049, "RPC_NT_CALL_IN_PROGRESS" },
	{ 0xC002004A, "RPC_NT_NO_MORE_BINDINGS" },
	{ 0xC002004B, "RPC_NT_GROUP_MEMBER_NOT_FOUND" },
	{ 0xC002004C, "EPT_NT_CANT_CREATE" },
	{ 0xC002004D, "RPC_NT_INVALID_OBJECT" },
	{ 0xC002004F, "RPC_NT_NO_INTERFACES" },
	{ 0xC0020050, "RPC_NT_CALL_CANCELLED" },
	{ 0xC0020051, "RPC_NT_BINDING_INCOMPLETE" },
	{ 0xC0020052, "RPC_NT_COMM_FAILURE" },
	{ 0xC0020053, "RPC_NT_UNSUPPORTED_AUTHN_LEVEL" },
	{ 0xC0020054, "RPC_NT_NO_PRINC_NAME" },
	{ 0xC0020055, "RPC_NT_NOT_RPC_ERROR" },
	{ 0xC0020057, "RPC_NT_SEC_PKG_ERROR" },
	{ 0xC0020058, "RPC_NT_NOT_CANCELLED" },
	{ 0xC0021007, "RPC_P_RECEIVE_ALERTED" },
	{ 0xC0021008, "RPC_P_CONNECTION_CLOSED" },
	{ 0xC0021009, "RPC_P_RECEIVE_FAILED" },
	{ 0xC002100A, "RPC_P_SEND_FAILED" },
	{ 0xC002100B, "RPC_P_TIMEOUT" },
	{ 0xC002100C, "RPC_P_SERVER_TRANSPORT_ERROR" },
	{ 0xC002100E, "RPC_P_EXCEPTION_OCCURRED" },
	{ 0xC0021012, "RPC_P_CONNECTION_SHUTDOWN" },
	{ 0xC0021015, "RPC_P_THREAD_LISTENING" },
	{ 0xC0030001, "RPC_NT_NO_MORE_ENTRIES" },
	{ 0xC0030002, "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL" },
	{ 0xC0030003, "RPC_NT_SS_CHAR_TRANS_SHORT_FILE" },
	{ 0xC0030004, "RPC_NT_SS_IN_NULL_CONTEXT" },
	{ 0xC0030005, "RPC_NT_SS_CONTEXT_MISMATCH" },
	{ 0xC0030006, "RPC_NT_SS_CONTEXT_DAMAGED" },
	{ 0xC0030007, "RPC_NT_SS_HANDLES_MISMATCH" },
	{ 0xC0030008, "RPC_NT_SS_CANNOT_GET_CALL_HANDLE" },
	{ 0xC0030009, "RPC_NT_NULL_REF_POINTER" },
	{ 0xC003000A, "RPC_NT_ENUM_VALUE_OUT_OF_RANGE" },
	{ 0xC003000B, "RPC_NT_BYTE_COUNT_TOO_SMALL" },
	{ 0xC003000C, "RPC_NT_BAD_STUB_DATA" },
	{ 0xC0030059, "RPC_NT_INVALID_ES_ACTION" },
	{ 0xC003005A, "RPC_NT_WRONG_ES_VERSION" },
	{ 0xC003005B, "RPC_NT_WRONG_STUB_VERSION" },
	{ 0xC003005C, "RPC_NT_INVALID_PIPE_OBJECT" },
	{ 0xC003005D, "RPC_NT_INVALID_PIPE_OPERATION" },
	{ 0xC003005E, "RPC_NT_WRONG_PIPE_VERSION" },
	{ 0xC05C0000, "STATUS_SVHDX_ERROR_STORED" },
	{ 0xC05CFF00, "STATUS_SVHDX_ERROR_NOT_AVAILABLE" },
	{ 0xC05CFF01, "STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE" },
	{ 0xC05CFF02, "STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED" },
	{ 0xC05CFF03, "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED" },
	{ 0xC05CFF04, "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED" },
	{ 0xC05CFF05, "STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED" },
	{ 0xC05CFF06, "STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED" },
	{ 0xC05CFF07, "STATUS_SVHDX_RESERVATION_CONFLICT" },
	{ 0xC05CFF08, "STATUS_SVHDX_WRONG_FILE_TYPE" },
	{ 0xC05CFF09, "STATUS_SVHDX_VERSION_MISMATCH" },
	{ 0xC05CFF0A, "STATUS_VHD_SHARED" },
	{ 0,          NULL }
};
value_string_ext NT_errors_ext = VALUE_STRING_EXT_INIT(NT_errors);

/* These are the MS country codes from

	https://web.archive.org/web/20081224015707/http://www.unicode.org/unicode/onlinedat/countries.html

   For countries that share the same number, I choose to use only the
   name of the largest country. Apologies for this. If this offends you,
   here is the table to change that.

   This also includes the code of 0 for "Default", which isn't in
   that list, but is in Microsoft's SDKs and the Cygnus "winnls.h"
   header file.  Presumably it means "don't override the setting
   on the user's machine".

   Future versions of Microsoft's "winnls.h" header file might include
   additional codes; the current version matches the Unicode Consortium's
   table.
*/
static const value_string ms_country_codes[] = {
	{  0,	"Default"},
	{  1,	"USA"},
	{  2,	"Canada"},
	{  7,	"Russia"},
	{ 20,	"Egypt"},
	{ 27,	"South Africa"},
	{ 30,	"Greece"},
	{ 31,	"Netherlands"},
	{ 32,	"Belgium"},
	{ 33,	"France"},
	{ 34,	"Spain"},
	{ 36,	"Hungary"},
	{ 39,	"Italy"},
	{ 40,	"Romania"},
	{ 41,	"Switzerland"},
	{ 43,	"Austria"},
	{ 44,	"United Kingdom"},
	{ 45,	"Denmark"},
	{ 46,	"Sweden"},
	{ 47,	"Norway"},
	{ 48,	"Poland"},
	{ 49,	"Germany"},
	{ 51,	"Peru"},
	{ 52,	"Mexico"},
	{ 54,	"Argentina"},
	{ 55,	"Brazil"},
	{ 56,	"Chile"},
	{ 57,	"Colombia"},
	{ 58,	"Venezuela"},
	{ 60,	"Malaysia"},
	{ 61,	"Australia"},
	{ 62,	"Indonesia"},
	{ 63,	"Philippines"},
	{ 64,	"New Zealand"},
	{ 65,	"Singapore"},
	{ 66,	"Thailand"},
	{ 81,	"Japan"},
	{ 82,	"South Korea"},
	{ 84,	"Viet Nam"},
	{ 86,	"China"},
	{ 90,	"Turkey"},
	{ 91,	"India"},
	{ 92,	"Pakistan"},
	{212,	"Morocco"},
	{213,	"Algeria"},
	{216,	"Tunisia"},
	{218,	"Libya"},
	{254,	"Kenya"},
	{263,	"Zimbabwe"},
	{298,	"Faroe Islands"},
	{351,	"Portugal"},
	{352,	"Luxembourg"},
	{353,	"Ireland"},
	{354,	"Iceland"},
	{355,	"Albania"},
	{358,	"Finland"},
	{359,	"Bulgaria"},
	{370,	"Lithuania"},
	{371,	"Latvia"},
	{372,	"Estonia"},
	{374,	"Armenia"},
	{375,	"Belarus"},
	{380,	"Ukraine"},
	{381,	"Serbia"},
	{385,	"Croatia"},
	{386,	"Slovenia"},
	{389,	"Macedonia"},
	{420,	"Czech Republic"},
	{421,	"Slovak Republic"},
	{501,	"Belize"},
	{502,	"Guatemala"},
	{503,	"El Salvador"},
	{504,	"Honduras"},
	{505,	"Nicaragua"},
	{506,	"Costa Rica"},
	{507,	"Panama"},
	{591,	"Bolivia"},
	{593,	"Ecuador"},
	{595,	"Paraguay"},
	{598,	"Uruguay"},
	{673,	"Brunei Darussalam"},
	{852,	"Hong Kong"},
	{853,	"Macau"},
	{886,	"Taiwan"},
	{960,	"Maldives"},
	{961,	"Lebanon"},
	{962,	"Jordan"},
	{963,	"Syria"},
	{964,	"Iraq"},
	{965,	"Kuwait"},
	{966,	"Saudi Arabia"},
	{967,	"Yemen"},
	{968,	"Oman"},
	{971,	"United Arab Emirates"},
	{972,	"Israel"},
	{973,	"Bahrain"},
	{974,	"Qatar"},
	{976,	"Mongolia"},
	{981,	"Iran"},
	{994,	"Azerbaijan"},
	{995,	"Georgia"},
	{996,	"Kyrgyzstan"},

	{0,	NULL}
};
value_string_ext ms_country_codes_ext = VALUE_STRING_EXT_INIT(ms_country_codes);

 /*module_t* module;*/
 /*pref_t* sid_display_hex;*/

static proto_item *
add_nttime(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date,
	   uint64_t filetime)
{
	proto_item *item;
	nstime_t ts;

	if (filetime == 0) {
		ts.secs = 0;
		ts.nsecs = 0;
		item = proto_tree_add_time_format_value(tree, hf_date, tvb, offset, 8,
		    &ts, "No time specified (0)");
	} else if (filetime == UINT64_C(0x8000000000000000)) {
		ts.secs = 0;
		ts.nsecs = 0x80000000;
		item = proto_tree_add_time_format_value(tree, hf_date, tvb, offset, 8,
		    &ts, "Infinity (relative time)");
	} else if (filetime == UINT64_C(0x7fffffffffffffff)) {
		ts.secs = 0xffffffff;
		ts.nsecs = 0x7fffffff;
		item = proto_tree_add_time_format_value(tree, hf_date, tvb, offset, 8,
		    &ts, "Infinity (absolute time)");
	} else {
		if (filetime_to_nstime(&ts, filetime)) {
			item = proto_tree_add_time(tree, hf_date, tvb,
			    offset, 8, &ts);
		} else {
			item = proto_tree_add_time_format_value(tree, hf_date, tvb, offset, 8,
			    &ts, "Time can't be converted");
		}
	}
	return item;
}

proto_item *
dissect_nttime(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date, const unsigned encoding)
{
	if (tree) {
		uint32_t filetime_high, filetime_low;
		uint64_t filetime;

		filetime_low = tvb_get_uint32(tvb, offset, encoding);
		filetime_high = tvb_get_uint32(tvb, offset + 4, encoding);
		filetime =  ((uint64_t)filetime_high << 32) | filetime_low;
		return add_nttime(tvb, tree, offset, hf_date, filetime);
	}
	return NULL;
}

proto_item *
dissect_nttime_hyper(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date, const unsigned encoding)
{
	if (tree) {
		uint64_t filetime;

		filetime = tvb_get_uint64(tvb, offset, encoding);
		return add_nttime(tvb, tree, offset, hf_date, filetime);
	}
	return NULL;
}

proto_item *
dissect_nttime_hyper_1sec(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date, const unsigned encoding)
{
	if (tree) {
		uint64_t ftsecs;
		nstime_t ts;

		ftsecs = tvb_get_uint64(tvb, offset, encoding);
		if (filetime_1sec_to_nstime(&ts, ftsecs)) {
			return proto_tree_add_time(tree, hf_date, tvb,
			    offset, 8, &ts);
		} else {
			ts.secs = ftsecs;
			ts.nsecs = 0;
			return proto_tree_add_time_format_value(tree, hf_date, tvb, offset, 8,
			    &ts, "Time can't be converted");
		}
	}
	return NULL;
}

/* Well-known SIDs defined in

     https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
*/
static const sid_strings well_known_sids[] = {
	{"S-1-0",          "Null Authority"},
	{"S-1-0-0",        "Nobody"},
	{"S-1-1",          "World Authority"},
	{"S-1-1-0",        "Everyone"},
	{"S-1-2",          "Local Authority"},
	{"S-1-2-0",        "Local"},
	{"S-1-2-1",        "Console Logon"},
	{"S-1-3",          "Creator Authority"},
	{"S-1-3-0",        "Creator Owner"},
	{"S-1-3-1",        "Creator Group"},
	{"S-1-3-2",        "Creator Owner Server"},
	{"S-1-3-3",        "Creator Group Server"},
	{"S-1-3-4",        "Owner Rights"},
	{"S-1-4",          "Non-unique Authority"},

	{"S-1-5",          "NT Authority"},
	{"S-1-5-1",        "Dialup"},
	{"S-1-5-2",        "Network"},
	{"S-1-5-3",        "Batch"},
	{"S-1-5-4",        "Interactive"},
	{"S-1-5-5",        "Logon Session"}, /* S-1-5-5-X-Y has 6 fields */
	{"S-1-5-6",        "Service"},
	{"S-1-5-7",        "Anonymous"},
	{"S-1-5-8",        "Proxy"},
	{"S-1-5-9",        "Enterprise Domain Controllers"},
	{"S-1-5-10",       "Principal Self"},
	{"S-1-5-11",       "Authenticated Users"},
	{"S-1-5-12",       "Restricted Code"},
	{"S-1-5-13",       "Terminal Server Users"},
	{"S-1-5-14",       "Remote Interactive Logon"},
	{"S-1-5-15",       "All users in this organization"},
	{"S-1-5-17",       "Default IIS user account"},
	{"S-1-5-18",       "Local System"},
	{"S-1-5-19",       "Local Service"},
	{"S-1-5-20",       "Network Service"},

	{"S-1-5-21-0-0-0-496", "Compounded Authentication"},
	{"S-1-5-21-0-0-0-497", "Claims Valid"},

	/*
	 * S-1-5-21-<d1>-<d2>-<d3>-<RID> where "<d1>-<d2>-<d3>" is the NT domain
	 *          RIDs are defined in 'wkwn_S_1_5_21_rids' */
	{"S-1-5-21",       "Domain SID"},

	/* S-1-5-32-<RID>: Builtin local group SIDs  */
	{"S-1-5-32",       "Local Group"},
	{"S-1-5-32-544",   "Administrators"},
	{"S-1-5-32-545",   "Users"},
	{"S-1-5-32-546",   "Guests"},
	{"S-1-5-32-547",   "Power Users"},
	{"S-1-5-32-548",   "Account Operators"},
	{"S-1-5-32-549",   "Server Operators"},
	{"S-1-5-32-550",   "Print Operators"},
	{"S-1-5-32-551",   "Backup Operators"},
	{"S-1-5-32-552",   "Replicators"},
	{"S-1-5-32-554",   "Pre-Windows 2000 Compatible Access"},
	{"S-1-5-32-555",   "Remote Desktop Users"},
	{"S-1-5-32-556",   "Network Configuration Operators"},
	{"S-1-5-32-557",   "Incoming Forest Trust Builders"},
	{"S-1-5-32-558",   "Performance Monitor Users"},
	{"S-1-5-32-559",   "Performance Log Users"},
	{"S-1-5-32-560",   "Windows Authorization Access Group"},
	{"S-1-5-32-561",   "Terminal Server License Servers"},
	{"S-1-5-32-562",   "Distributed COM Users"},
	{"S-1-5-32-568",   "IIS Users"},
	{"S-1-5-32-569",   "Cryptographic Operators"},
	{"S-1-5-32-573",   "Event Log Readers"},
	{"S-1-5-32-574",   "Certificate Service DCOM Access"},
	{"S-1-5-32-575",   "RDS Remote Access Servers"},
	{"S-1-5-32-576",   "RDS Endpoint Servers"},
	{"S-1-5-32-577",   "RDS Management Servers"},
	{"S-1-5-32-578",   "Hyper-V Admins"},
	{"S-1-5-32-579",   "Access Control Assistance Operators"},
	{"S-1-5-32-580",   "Remote Management Users"},

	{"S-1-5-33",       "Write Restricted Code"},

	{"S-1-5-64",       "Authentication"},
	{"S-1-5-64-10",    "NTLM"},
	{"S-1-5-64-14",    "SChannel"},
	{"S-1-5-64-21",    "Digest"},

	{"S-1-5-80",       "NT Service"},

	{"S-1-5-84-0-0-0-0-0", "User Mode Drivers"},

	{"S-1-5-113",      "Local Account"},
	{"S-1-5-114",      "Local Administrator Account"},

	{"S-1-5-1000",     "Other Organisation"},

	{"S-1-15-2-1",     "All App Packages"},

	{"S-1-16",         "Mandatory Level"},
	{"S-1-16-0",       "Untrusted"},
	{"S-1-16-4096",    "Low"},
	{"S-1-16-8192",    "Medium"},
	{"S-1-16-8448",    "Medium Plus"},
	{"S-1-16-12288",   "High"},
	{"S-1-16-16384",   "System"},
	{"S-1-16-20480",   "Protected Process"},
	{"S-1-16-28672",   "Secure Process"},

	{"S-1-18-1",       "Authentication Authority Asserted Identity"},
	{"S-1-18-2",       "Service Asserted Identity"},
	{"S-1-18-3",       "Fresh Public Key Identity"},
	{"S-1-18-4",       "Key Trust Identity"},
	{"S-1-18-5",       "Key Property Multifactor Authentication"},
	{"S-1-18-6",       "Key Property Attestation"},

	{NULL, NULL}
};

static const char*
match_wkwn_sids(const char* sid) {
	int i = 0;
	while (well_known_sids[i].name) {
		if (strcmp(well_known_sids[i].sid, sid)==0) {
			return well_known_sids[i].name;
		}
		i++;
	}
	return NULL;
}

/* For SIDs in the form 'S-1-5-21-X-Y-Z-<RID>', '21-X-Y-Z' is referred to
   as the "domain SID" (NT domain) or "machine SID" (local machine).
   The following are well-known RIDs which are appended to domain/machine SIDs
   as defined in

     https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
*/
static const value_string wkwn_S_1_5_21_rids[] = {
	{496,	"Compounded Authentication"},
	{497,	"Claims Valid"},
	{498,   "Enterprise Read-only Domain Controllers"},
	{500,	"Administrator"},
	{501,	"Guest"},
	{502,	"KRBTGT"},
	{512,	"Domain Admins"},
	{513,	"Domain Users"},
	{514,	"Domain Guests"},
	{515,	"Domain Computers"},
	{516,	"Domain Controllers"},
	{517,	"Cert Publishers"},
	{518,	"Schema Administrators"},
	{519,	"Enterprise Admins"},
	{520,	"Group Policy Creator Owners"},
	{521,	"Read-only Domain Controllers"},
	{522,	"Cloneable Controllers"},
	{525,	"Protected Users"},
	{526,	"Key Admins"},
	{527,	"Enterprise Key Admins"},
	{553,	"RAS and IAS Servers"},
	{571,	"Allowed RODC Password Replication Group"},
	{572,	"Denied RODC Password Replication Group"},
	{0, NULL}
};
static value_string_ext wkwn_S_1_5_21_rids_ext = VALUE_STRING_EXT_INIT(wkwn_S_1_5_21_rids);

/* Dissect an NT SID.  Label it with 'name' and return a string version
 * of the SID in the 'sid_str' parameter which has a packet lifetime
 * scope and should NOT be freed by the caller. hf_sid can be -1 if
 * the caller doesn't care what name is used and then "nt.sid" will be
 * the default instead. If the caller wants a more appropriate hf
 * field, it will just pass a FT_STRING hf field here
 */
int
dissect_nt_sid(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
	       const char *name, char **sid_str, int hf_sid)
{
	int offset_sid_start = offset, sa_offset, rid_offset=0, wkwn_sid1_len=0,
		wkwn_sid2_len = 0, i;
	uint8_t revision, num_auth;
	uint32_t sa_field, rid=0;
	uint64_t authority=0;
	wmem_strbuf_t *sa_str = NULL, *sid_in_dec_str = NULL, *sid_in_hex_str = NULL, *label_str = NULL,
				  *domain_str = NULL, *wkwn_sid1_str = NULL, *wkwn_sid2_str = NULL;
	const char *mapped_name = NULL, *mapped_rid = NULL;
	bool domain_sid = false, s_1_5_32 = false, s_1_5_64 = false, locally_defined = false,
		S_1_16 = false;
	proto_item *item = NULL, *hidden_item;
	proto_tree *subtree = NULL;

	/* Revision of SID */
	revision = tvb_get_uint8(tvb, offset);
	offset++;

	/* Number of subauthority fields */
	num_auth = tvb_get_uint8(tvb, offset);
	offset++;

	if(sid_str)
		*sid_str=NULL;

	if(hf_sid <= 0){
		/* if no tree, just return the offset of the end_of_SID+1 */
		if (!parent_tree)
			return offset+(6+(num_auth*4));

		hf_sid=hf_nt_sid;
	}

	/* Identifier Authority */
	for(i=0; i<6; i++){
		authority = (authority << 8) + tvb_get_uint8(tvb, offset);
		offset++;
	}

	sid_in_dec_str = wmem_strbuf_create(wmem_packet_scope());
	wmem_strbuf_append_printf (sid_in_dec_str, "S-%u-%" PRIu64, revision, authority);

	/*  If sid_display_hex is set, sid_in_dec_str is still needed for
		looking up well-known SIDs*/
	if (sid_display_hex) {
		sid_in_hex_str = wmem_strbuf_create(wmem_packet_scope());
		wmem_strbuf_append_printf (sid_in_hex_str, "S-%x-%" PRIx64, revision, authority);
	}

	wkwn_sid1_str = wmem_strbuf_create(wmem_packet_scope());
	label_str = wmem_strbuf_create(wmem_packet_scope());

	if (strcmp(wmem_strbuf_get_str(sid_in_dec_str), "S-1-16")==0)
		S_1_16 = true;

	/* Check for Scoped Policy ID (S-1-17-<subauth1>...) */
	if (authority == 17) {
		mapped_name = "Central Access Policy";
	}

	/* Look for well-known SIDs in format 'S-1-<Identifier Authority>' (i.e., exactly 3 fields) */
	if (num_auth==0 || S_1_16 || mapped_name) {
		if (!mapped_name)
			mapped_name = match_wkwn_sids(wmem_strbuf_get_str(sid_in_dec_str));

		if (mapped_name) {
			wmem_strbuf_append(label_str, mapped_name);
			wmem_strbuf_append(wkwn_sid1_str,
				(sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str)));
			wkwn_sid1_len = 8;
		}
	}


	sa_offset = offset;
	sa_str = wmem_strbuf_create(wmem_packet_scope());
	wkwn_sid2_str = wmem_strbuf_create(wmem_packet_scope());
	domain_str = wmem_strbuf_create(wmem_packet_scope());

	/* Build the sub-authorities and full SID strings */
	for(i=1; i<num_auth+1; i++) {
	   /*
		* XXX should not be letohl but native byteorder according to
		* Samba header files.
		*
		* However, considering that there were never any NT ports
		* to big-endian platforms (PowerPC and MIPS ran little-endian,
		* and IA-64 runs little-endian, as does x86-64), we can (?)
		* assume that non le byte encodings will be "uncommon"?
		*/
		sa_field = tvb_get_letohl(tvb, offset);
		wmem_strbuf_append_printf(sid_in_dec_str, "-%u", sa_field);
		wmem_strbuf_append_printf(sa_str,
			(i==1 ? (sid_display_hex ? "%x" : "%u") : (sid_display_hex ? "-%x" : "-%u")),
			sa_field);
		if (sid_display_hex)
			wmem_strbuf_append_printf(sid_in_hex_str, "-%x", sa_field);

		if (i==1) {
			/* Look for well-known SIDs at level one ("S-1-<authority>-<value>") */
			if (S_1_16) {
				/* Mandatory Level (S-1-16) */
				mapped_rid = match_wkwn_sids(wmem_strbuf_get_str(sid_in_dec_str));
				if (mapped_rid) {
					/* Get the RID */
					wmem_strbuf_append_printf(label_str, "%s-%s", mapped_name, mapped_rid);
					rid = sa_field;
					rid_offset = offset;
					wmem_strbuf_append(wkwn_sid2_str,
						(sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str)));
					wkwn_sid1_len=12;				}
			} else {
				mapped_name = match_wkwn_sids(wmem_strbuf_get_str(sid_in_dec_str));
				if (mapped_name) {
					wmem_strbuf_append(label_str, mapped_name);
					wmem_strbuf_append(wkwn_sid1_str,
						(sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str)));
					wkwn_sid1_len = 12;
				}
				/* The following three SID types have (unique) RIDs */
				if (strcmp(wmem_strbuf_get_str(sid_in_dec_str), "S-1-5-21")==0) {
					/* Domain SID */
					domain_sid = true;
				} else if (strcmp(wmem_strbuf_get_str(sid_in_dec_str), "S-1-5-32")==0) {
					/* Local Group (S-1-5-32) SID */
					s_1_5_32 = true;
				} else if (strcmp(wmem_strbuf_get_str(sid_in_dec_str), "S-1-5-64")==0) {
					/* Authentication (S-1-5-64) SID */
					s_1_5_64 = true;
				}
			}
		} else if (i==2  && !domain_sid) {
			/* The only well-known SIDS with two subauthority fields ("level 2 SIDs") are
			   Local Group (S-1-5-32), and Authentication (S-1-5-64). */
			if (s_1_5_32 || s_1_5_64) {
				mapped_rid = match_wkwn_sids(wmem_strbuf_get_str(sid_in_dec_str));
				if (mapped_rid) {
					/* Get the RID */
					wmem_strbuf_append_printf(label_str, "-%s", mapped_rid);
					rid = sa_field;
					rid_offset = offset;
					wmem_strbuf_append(wkwn_sid2_str,
						(sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str)));
					wkwn_sid2_len=16;
				} else {
					/* The RID not well-known. */
					locally_defined = true;
				}
			} else {
				if (mapped_name) {
					/* A level 1 well-known SID appended with locally defined value */
					locally_defined = true;
				}
			}
		} else {
			/* 3 or more sub-auth fields - NOTE: Except for domain SIDs, there are no wkwn SIDs with 3 or more
			   sub-auth fields so we don't lookup SIDs here. Logon Session SIDs have 3 sub-auth fields but the
			   last two are locally defined. */
			if (domain_sid) {
				if (num_auth >= 4) {
					if (i >= 2 && i <=4 ) {
						/* Add the field to the domain string (d1-d2-d3) */
						wmem_strbuf_append_printf(domain_str,
							(i==2 ? (sid_display_hex ? "%x" : "%u") : (sid_display_hex ? "-%x" : "-%u")), sa_field);

					} else if (i==5) {
						rid = sa_field;
						rid_offset = offset;
						mapped_rid = val_to_str_ext_const(rid, &wkwn_S_1_5_21_rids_ext, "Domain RID");
						wmem_strbuf_append_printf(label_str, "-%s", mapped_rid);

					} else {
						locally_defined = true;
					}
				} else {
					mapped_name = "Corrupt domain SID";
				}
			} else {
				if (mapped_name) {
					/* A locally defined value appended to a level 2 well-known SID*/
					locally_defined = true;
				}
			}
		}
		offset+=4;
	} /* End of for loop */

	if ( !(mapped_name || domain_sid || s_1_5_32 || s_1_5_64) ) {
	    /* If requested, try to map the NON-well-known SID to an object name discovered in this capture  */
		if (sid_name_snooping) {
			mapped_name = find_sid_name(wmem_strbuf_get_str(sid_in_dec_str));
		} else {
			mapped_name = "<Unknown SID type>";
		}
	}

	if (locally_defined) {
		wmem_strbuf_append_printf(label_str, "-<locally defined>");
	}

	/* It's tree time
	   Display the full SID string in hex or dec */
	item = proto_tree_add_string_format(
		parent_tree, hf_sid, tvb, offset_sid_start, (offset - offset_sid_start),
		(sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str)),
		"%s: %s", name, (sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str))
	);

	if (wmem_strbuf_get_len(label_str) > 0) {
		proto_item_append_text(item, "  (%s)", wmem_strbuf_get_str(label_str));
	}

	subtree = proto_item_add_subtree(item, ett_nt_sid);

	/* Add revision, num_auth, and authority */
	proto_tree_add_item(subtree, hf_nt_sid_revision, tvb, offset_sid_start, 1, ENC_LITTLE_ENDIAN);
	proto_tree_add_item(subtree, hf_nt_sid_num_auth, tvb, offset_sid_start+1, 1, ENC_LITTLE_ENDIAN);
	proto_tree_add_uint64(subtree,
		(sid_display_hex ? hf_nt_sid_auth_hex : hf_nt_sid_auth_dec),
		tvb, offset_sid_start+2, 6, authority);

	/* Add subauthorities */
	proto_tree_add_string_format_value(subtree, hf_nt_sid_subauth, tvb, sa_offset,
		num_auth*4, wmem_strbuf_get_str(sa_str), "%s", wmem_strbuf_get_str(sa_str));

	if (rid) {
		item = proto_tree_add_item (subtree,
			(sid_display_hex ? hf_nt_sid_rid_hex : hf_nt_sid_rid_dec), tvb, rid_offset, 4, ENC_LITTLE_ENDIAN);

		if (mapped_rid)
			proto_item_append_text(item, "  (%s)", mapped_rid);
	}

	/* Add well-known SID and domain strings if present */
	if (wmem_strbuf_get_len(wkwn_sid1_str) > 0) {
		hidden_item = proto_tree_add_string_format_value(
			subtree, hf_nt_sid_wkwn, tvb, offset_sid_start, wkwn_sid1_len,
			wmem_strbuf_get_str(wkwn_sid1_str), "%s", wmem_strbuf_get_str(wkwn_sid1_str));

		if (mapped_name) {
			proto_item_append_text(hidden_item, "  (%s)", mapped_name);
		}
		proto_item_set_hidden(hidden_item);
	}
	if (wmem_strbuf_get_len(wkwn_sid2_str) > 0) {
		hidden_item = proto_tree_add_string_format_value(
			subtree, hf_nt_sid_wkwn, tvb, offset_sid_start, wkwn_sid2_len,
			wmem_strbuf_get_str(wkwn_sid2_str), "%s", wmem_strbuf_get_str(wkwn_sid2_str));
		if (wmem_strbuf_get_len(label_str) > 0) {
			proto_item_append_text(hidden_item, "  (%s)", wmem_strbuf_get_str(label_str));
		}
		proto_item_set_hidden(hidden_item);
	}
	if (domain_sid && wmem_strbuf_get_len(domain_str) > 0) {
		hidden_item = proto_tree_add_string_format_value(
			subtree, hf_nt_sid_domain, tvb, offset_sid_start + 12, 12,
			wmem_strbuf_get_str(domain_str), "%s", wmem_strbuf_get_str(domain_str));
		proto_item_set_hidden(hidden_item);
	}

	/* If requested, return SID string with mapped name */
	if(sid_str){
		if(wmem_strbuf_get_len(label_str) > 0){
			*sid_str = wmem_strdup_printf(wmem_packet_scope(), "%s  (%s)",
				(sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str)), wmem_strbuf_get_str(label_str));
		} else {
			*sid_str = wmem_strdup(wmem_packet_scope(), sid_display_hex ? wmem_strbuf_get_str(sid_in_hex_str) : wmem_strbuf_get_str(sid_in_dec_str));
		}
		if(!(*sid_str)){
			*sid_str=wmem_strdup(wmem_packet_scope(), "corrupted SID");
		}
	}
	return offset;
}

/* Dissect SYSTEM_RESOURCE_ATTRIBUTE_ACE Value, see [MS-DTYP] v20180912 section 2.4.4.15 */
static int
dissect_nt_ace_system_resource_attribute_value(tvbuff_t *tvb, int value_offset, proto_tree *tree,
					       uint16_t value_type, proto_item *sra_item)
{
	unsigned value_len;
	uint32_t blob_len;
	proto_item *value_item = NULL;
	char *value_str = NULL; /* packet scope, do not free */
	bool quote = false;
	switch (value_type) {
	    case CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
		value_len = sizeof(int64_t);
		value_item = proto_tree_add_item(tree, hf_nt_ace_sra_value_int64,
						 tvb, value_offset, value_len,
						 ENC_LITTLE_ENDIAN);
		value_offset += value_len;
		break;

	    case CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64:
		value_len = sizeof(uint64_t);
		value_item = proto_tree_add_item(tree, hf_nt_ace_sra_value_uint64,
						 tvb, value_offset, value_len,
						 ENC_LITTLE_ENDIAN);
		value_offset += value_len;
		break;

	    case CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING:
		value_len = tvb_unicode_strsize(tvb, value_offset);
		value_item = proto_tree_add_item(tree, hf_nt_ace_sra_value_string,
						 tvb, value_offset, value_len,
						 ENC_UTF_16 | ENC_LITTLE_ENDIAN);
		quote = true;
		value_offset += value_len;
		break;

	    case CLAIM_SECURITY_ATTRIBUTE_TYPE_SID:
		value_offset = dissect_nt_sid(tvb, value_offset, tree,
					      "SID", &value_str, hf_nt_ace_sra_value_sid);
		break;

	    case CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN:
		value_len = sizeof(uint64_t);
		value_item = proto_tree_add_item(tree, hf_nt_ace_sra_value_boolean,
						 tvb, value_offset, value_len,
						 ENC_LITTLE_ENDIAN);
		value_offset += value_len;
		break;

	    case CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING:
		blob_len = tvb_get_letohl(tvb, value_offset);
		value_offset += sizeof(blob_len);
		value_item = proto_tree_add_item(tree, hf_nt_ace_sra_value_octet_string,
						 tvb, value_offset, blob_len, ENC_NA);
		/* do not append binary to sra_item */
		value_str = "<bin>";
		value_offset += blob_len;
		break;

	    default:
		break;
	}

	if (sra_item) {
		if ((value_str == NULL) && value_item) {
			value_str = proto_item_get_display_repr(wmem_packet_scope(), value_item);
		}

		if (value_str == NULL) {
			/* missing system resource attribute value */
			value_str = "???";
		}

		if (value_str) {
			proto_item_append_text(sra_item,
					       (quote) ? "\"%s\"" : "%s",
					       value_str);
		}
	}

	return value_offset;
}

/* Dissect SYSTEM_RESOURCE_ATTRIBUTE_ACE, see [MS-DTYP] v20180912 section 2.4.4.15 */
static int
dissect_nt_ace_system_resource_attribute(tvbuff_t *tvb, int offset, uint16_t size, proto_tree *parent_tree)
{
	/* The caller has already dissected Header, Mask and Sid. Therefore
	   this function only dissects Attribute Data. This data takes
	   the form of a CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1. The
	   following code dissects the structure piecemeal */
	int start_offset = offset;
	uint32_t name; /* offset, relative to start_offset */
	uint16_t value_type;
	uint32_t value_count;

	/* Add a subtree to hold the system resource attribute details */
	proto_item *sra_item;
	proto_tree *sra_tree;
	sra_item = proto_tree_add_item(parent_tree, hf_nt_ace_sra, tvb, offset, size, ENC_NA);
	sra_tree = proto_item_add_subtree(sra_item, ett_nt_ace_sra);

	/* Name offset */
	name = tvb_get_letohl(tvb, offset);
	proto_tree_add_uint(sra_tree, hf_nt_ace_sra_name_offset,
			    tvb, offset, sizeof(name), name);

	int name_offset = (start_offset + name);
	unsigned name_len = tvb_unicode_strsize(tvb, name_offset);
	proto_item *name_item;
	name_item = proto_tree_add_item(sra_tree, hf_nt_ace_sra_name,
					tvb, name_offset, name_len,
					ENC_UTF_16 | ENC_LITTLE_ENDIAN);
	proto_item_append_text(sra_item, ": %s=",
			       proto_item_get_display_repr(wmem_packet_scope(), name_item));
	offset += sizeof(name);

	/* ValueType */
	value_type = tvb_get_letohs(tvb, offset);
	proto_tree_add_uint(sra_tree, hf_nt_ace_sra_type,
			    tvb, offset, sizeof(value_type), value_type);
	offset += sizeof(value_type);

	/* Reserved */
	proto_tree_add_item(sra_tree, hf_nt_ace_sra_reserved,
			    tvb, offset, sizeof(uint16_t),
			    ENC_LITTLE_ENDIAN);
	offset += sizeof(uint16_t);

	/* Flags */
	static int * const flags[] = {
		&hf_nt_ace_sra_flags_policy_derived,
		&hf_nt_ace_sra_flags_manual,
		&hf_nt_ace_sra_flags_mandatory,
		&hf_nt_ace_sra_flags_disabled,
		&hf_nt_ace_sra_flags_disabled_by_default,
		&hf_nt_ace_sra_flags_deny_only,
		&hf_nt_ace_sra_flags_case_sensitive,
		&hf_nt_ace_sra_flags_non_inheritable,
		NULL
	};

	proto_tree_add_bitmask(sra_tree, tvb, offset, hf_nt_ace_sra_flags,
			       ett_nt_ace_sra_flags, flags, ENC_LITTLE_ENDIAN);
	offset += sizeof(uint32_t);

	/* ValueCount */
	value_count = tvb_get_letohl(tvb, offset);
	proto_tree_add_uint(sra_tree, hf_nt_ace_sra_value_count,
			    tvb, offset, sizeof(value_count), value_count);
	offset += sizeof(value_count);

	/* Value Offsets and Values */
	uint32_t value_offset;
	proto_tree *value_offset_tree = sra_tree;
	proto_tree *value_tree = sra_tree;
	if (value_count > 1) {
		/* Use independent value offset and value trees when
		   there are multiple values. */
		int value_offset_tree_offset = offset;
		int value_offset_tree_len = value_count * sizeof(value_offset);
		value_offset_tree = proto_tree_add_subtree(sra_tree, tvb,
							   value_offset_tree_offset,
							   value_offset_tree_len,
							   ett_nt_ace_sra_value_offsets,
							   NULL, "Value Offsets");

		/* The range associated with the value tree will
		   include some non-value data (but that's fine as the
		   value items it contains will have accurate ranges) */
		int value_tree_offset = value_offset_tree_offset + value_offset_tree_len;
		int value_tree_len = (start_offset + size) - value_tree_offset;
		value_tree = proto_tree_add_subtree(sra_tree, tvb,
						    value_tree_offset,
						    value_tree_len,
						    ett_nt_ace_sra_values,
						    NULL, "Values");
	}

	proto_item_append_text(sra_item, "{");
	for (uint32_t i = 0; i < value_count; ++i) {
		if (i) {
			proto_item_append_text(sra_item, ", ");
		}
		value_offset = tvb_get_letohl(tvb, offset);
		proto_tree_add_uint(value_offset_tree, hf_nt_ace_sra_value_offset,
				    tvb, offset, sizeof(value_offset), value_offset);
		dissect_nt_ace_system_resource_attribute_value(tvb, start_offset + value_offset,
							       value_tree, value_type, sra_item);
		offset += sizeof(value_offset);
	}
	proto_item_append_text(sra_item, "}");

	return start_offset + size;
}

/* Dissect Condition ACE token, see [MS-DTYP] v20180912 section 2.4.4.17.4 */
static int
// NOLINTNEXTLINE(misc-no-recursion)
dissect_nt_conditional_ace_token(tvbuff_t *tvb, packet_info *pinfo, int offset, uint16_t size, proto_tree *parent_tree)
{
	int start_offset = offset;
	proto_tree *tree = parent_tree;
	proto_item *item = NULL;
	uint8_t token = tvb_get_uint8(tvb, offset);
	uint32_t len;

	item = proto_tree_add_uint(tree, hf_nt_ace_cond_token,
				   tvb, offset, sizeof(token), token);

	if (ace_cond_token_has_data(token)) {
		tree = proto_item_add_subtree(item, ett_nt_ace_cond_data);
	}
	offset += sizeof(token);

	switch (token) {
	    case COND_ACE_TOKEN_INT8:
		proto_tree_add_item(tree, hf_nt_ace_cond_value_int8,
				    tvb, offset, sizeof(uint64_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint64_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_sign,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_base,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);
		break;

	    case COND_ACE_TOKEN_INT16:
		proto_tree_add_item(tree, hf_nt_ace_cond_value_int16,
				    tvb, offset, sizeof(uint64_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint64_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_sign,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_base,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);
		break;

	    case COND_ACE_TOKEN_INT32:
		proto_tree_add_item(tree, hf_nt_ace_cond_value_int32,
				    tvb, offset, sizeof(uint64_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint64_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_sign,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_base,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);
		break;

	    case COND_ACE_TOKEN_INT64:
		proto_tree_add_item(tree, hf_nt_ace_cond_value_int64,
				    tvb, offset, sizeof(uint64_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint64_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_sign,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);

		proto_tree_add_item(tree, hf_nt_ace_cond_base,
				    tvb, offset, sizeof(uint8_t),
				    ENC_LITTLE_ENDIAN);
		offset += sizeof(uint8_t);
		break;

	    case COND_ACE_TOKEN_UNICODE_STRING:
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);

		proto_tree_add_item(tree, hf_nt_ace_cond_value_string,
				    tvb, offset, len,
				    ENC_UTF_16 | ENC_LITTLE_ENDIAN);
		offset += len;
		break;

	    case COND_ACE_TOKEN_OCTET_STRING:
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);

		proto_tree_add_item(tree, hf_nt_ace_cond_value_octet_string,
				    tvb, offset, len, ENC_NA);
		offset += len;
		break;

	    case COND_ACE_TOKEN_COMPOSITE:
		/* Create another tree for composite */
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);
		if (len) {
			int remaining = size - (offset - start_offset);
			if (remaining >= (int)len) {
				int end_offset = offset + len;
				increment_dissection_depth(pinfo);
				while (offset < end_offset) {
					offset = dissect_nt_conditional_ace_token(tvb, pinfo, offset, remaining, tree);
				}
				decrement_dissection_depth(pinfo);
			} else {
				/* malformed: composite len is longer
				 * than the remaining data in the ace
				 */
				offset += remaining;
			}
		}
		break;

	    case COND_ACE_TOKEN_SID:
		offset += sizeof(len);

		offset = dissect_nt_sid(tvb, offset, tree, "SID", NULL, -1);
		break;

	    case COND_ACE_TOKEN_LOCAL_ATTRIBUTE:
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);

		proto_tree_add_item(tree, hf_nt_ace_cond_local_attr,
				    tvb, offset, len,
				    ENC_UTF_16 | ENC_LITTLE_ENDIAN);
		offset += len;
		break;

	    case COND_ACE_TOKEN_USER_ATTRIBUTE:
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);

		proto_tree_add_item(tree, hf_nt_ace_cond_user_attr,
				    tvb, offset, len,
				    ENC_UTF_16 | ENC_LITTLE_ENDIAN);
		offset += len;
		break;

	    case COND_ACE_TOKEN_RESOURCE_ATTRIBUTE:
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);

		proto_tree_add_item(tree, hf_nt_ace_cond_resource_attr,
				    tvb, offset, len,
				    ENC_UTF_16 | ENC_LITTLE_ENDIAN);
		offset += len;
		break;

	    case COND_ACE_TOKEN_DEVICE_ATTRIBUTE:
		len = tvb_get_letohl(tvb, offset); /* in bytes */
		offset += sizeof(len);

		proto_tree_add_item(tree, hf_nt_ace_cond_device_attr,
				    tvb, offset, len,
				    ENC_UTF_16 | ENC_LITTLE_ENDIAN);
		offset += len;
		break;

	    default:
		DISSECTOR_ASSERT(!ace_cond_token_has_data(token));
		break;
	}

	proto_item_set_len(item, offset - start_offset);
	return offset;
}


/* Dissect Conditional ACE (if present), see [MS-DTYP] v20180912 section 2.4.4.17.4 */
static int
dissect_nt_conditional_ace(tvbuff_t *tvb, packet_info *pinfo, int offset, uint16_t size, proto_tree *parent_tree)
{
	int start_offset = offset;

	/* Conditional ACE Application Data starts with "artx" */
	if (size >= 4) {
		const uint32_t artx = 0x78747261; /* "xtra" (LE) */
		uint32_t prefix = tvb_get_letohl(tvb, offset);
		offset += sizeof(prefix);

		if (prefix == artx) {
			/* Add a subtree to hold the condition expression tokens */
			proto_item *item = NULL;
			item = proto_tree_add_item(parent_tree, hf_nt_ace_cond, tvb, start_offset, size, ENC_NA);
			parent_tree = proto_item_add_subtree(item, ett_nt_ace_cond);

			/* Add the tokens to the subtree */
			int remaining;
			while (true) {
				remaining = size - (offset - start_offset);
				if (remaining <= 0)
					break;
				offset = dissect_nt_conditional_ace_token(tvb, pinfo, offset, remaining, parent_tree);
			}
		}
	}
	return start_offset + size;
}

/* Dissect an access mask.  All this stuff is kind of explained at

     https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask-format

*/
static int ett_nt_access_mask;
static int ett_nt_access_mask_generic;
static int ett_nt_access_mask_standard;
static int ett_nt_access_mask_specific;

static int hf_access_sacl;
static int hf_access_maximum_allowed;
static int hf_access_generic_read;
static int hf_access_generic_write;
static int hf_access_generic_execute;
static int hf_access_generic_all;
static int hf_access_standard_delete;
static int hf_access_standard_read_control;
static int hf_access_standard_synchronise;
static int hf_access_standard_write_dac;
static int hf_access_standard_write_owner;
static int hf_access_specific_15;
static int hf_access_specific_14;
static int hf_access_specific_13;
static int hf_access_specific_12;
static int hf_access_specific_11;
static int hf_access_specific_10;
static int hf_access_specific_9;
static int hf_access_specific_8;
static int hf_access_specific_7;
static int hf_access_specific_6;
static int hf_access_specific_5;
static int hf_access_specific_4;
static int hf_access_specific_3;
static int hf_access_specific_2;
static int hf_access_specific_1;
static int hf_access_specific_0;

/* Map generic permissions to specific permissions */

static void map_generic_access(uint32_t *access_mask,
			       struct generic_mapping *mapping)
{
	if (*access_mask & GENERIC_READ_ACCESS) {
		*access_mask &= ~GENERIC_READ_ACCESS;
		*access_mask |= mapping->generic_read;
	}

	if (*access_mask & GENERIC_WRITE_ACCESS) {
		*access_mask &= ~GENERIC_WRITE_ACCESS;
		*access_mask |= mapping->generic_write;
	}

	if (*access_mask & GENERIC_EXECUTE_ACCESS) {
		*access_mask &= ~GENERIC_EXECUTE_ACCESS;
		*access_mask |= mapping->generic_execute;
	}

	if (*access_mask & GENERIC_ALL_ACCESS) {
		*access_mask &= ~GENERIC_ALL_ACCESS;
		*access_mask |= mapping->generic_all;
	}
}

/* Map standard permissions to specific permissions */

static void map_standard_access(uint32_t *access_mask,
				struct standard_mapping *mapping)
{
	if (*access_mask & READ_CONTROL_ACCESS) {
		*access_mask &= ~READ_CONTROL_ACCESS;
		*access_mask |= mapping->std_read;
	}

	if (*access_mask & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|
			    SYNCHRONIZE_ACCESS)) {
		*access_mask &= ~(DELETE_ACCESS|WRITE_DAC_ACCESS|
				  WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS);
		*access_mask |= mapping->std_all;
	}

}

int
dissect_nt_access_mask(tvbuff_t *tvb, int offset, packet_info *pinfo,
		       proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex,
		       struct access_mask_info *ami, uint32_t *perms)
{
	proto_item *item;
	proto_tree *subtree, *generic_tree, *standard_tree, *specific_tree;
	uint32_t access;

	static int * const generic_access_flags[] = {
		&hf_access_generic_read,
		&hf_access_generic_write,
		&hf_access_generic_execute,
		&hf_access_generic_all,
		&hf_access_maximum_allowed,
		&hf_access_sacl,
		NULL
	};

	static int * const standard_access_flags[] = {
		&hf_access_standard_synchronise,
		&hf_access_standard_write_owner,
		&hf_access_standard_write_dac,
		&hf_access_standard_read_control,
		&hf_access_standard_delete,
		NULL
	};

	static int * const access_specific_flags[] = {
		&hf_access_specific_15,
		&hf_access_specific_14,
		&hf_access_specific_13,
		&hf_access_specific_12,
		&hf_access_specific_11,
		&hf_access_specific_10,
		&hf_access_specific_9,
		&hf_access_specific_8,
		&hf_access_specific_7,
		&hf_access_specific_6,
		&hf_access_specific_5,
		&hf_access_specific_4,
		&hf_access_specific_3,
		&hf_access_specific_2,
		&hf_access_specific_1,
		&hf_access_specific_0,
		NULL
	};

	if (drep != NULL) {
		/*
		 * Called from a DCE RPC protocol dissector, for a
		 * protocol where a 32-bit NDR integer contains
		 * an NT access mask; extract the access mask
		 * with an NDR call.
		 */
		offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, di, drep,
					    hfindex, &access);
	} else {
		/*
		 * Called from SMB, where the access mask is just a
		 * 4-byte little-endian quantity with no special
		 * NDR alignment requirement; extract it with
		 * "tvb_get_letohl()".
		 */
		access = tvb_get_letohl(tvb, offset);
		offset += 4;
	}

	if (perms) {
	  *perms = access;
	}

	item = proto_tree_add_uint(tree, hfindex, tvb, offset - 4, 4, access);

	subtree = proto_item_add_subtree(item, ett_nt_access_mask);

	/* Generic access rights */

	generic_tree = proto_tree_add_subtree_format(subtree, tvb, offset - 4, 4,
				   ett_nt_access_mask_generic, NULL, "Generic rights: 0x%08x",
				   access & GENERIC_RIGHTS_MASK);

	proto_tree_add_bitmask_list_value(generic_tree, tvb, offset - 4, 4, generic_access_flags, access);

	/* Standard access rights */

	standard_tree = proto_tree_add_subtree_format(subtree, tvb, offset - 4, 4,
				   ett_nt_access_mask_standard, NULL, "Standard rights: 0x%08x",
				   access & STANDARD_RIGHTS_MASK);

	proto_tree_add_bitmask_list_value(standard_tree, tvb, offset - 4, 4, standard_access_flags, access);

	/* Specific access rights.  Call the specific_rights_fn
	   pointer if we have one, otherwise just display bits 0-15 in
	   boring fashion. */

	if (ami && ami->specific_rights_name)
		specific_tree = proto_tree_add_subtree_format(subtree, tvb, offset - 4, 4,
					   ett_nt_access_mask_specific, &item, "%s specific rights: 0x%08x",
					   ami->specific_rights_name,
					   access & SPECIFIC_RIGHTS_MASK);
	else
		specific_tree = proto_tree_add_subtree_format(subtree, tvb, offset - 4, 4,
					   ett_nt_access_mask_specific, &item, "Specific rights: 0x%08x",
					   access & SPECIFIC_RIGHTS_MASK);

	if (ami && ami->specific_rights_fn) {
		uint32_t mapped_access = access;
		proto_tree *specific_mapped;

		specific_mapped = proto_item_add_subtree(
			item, ett_nt_access_mask_specific);

		ami->specific_rights_fn(
			tvb, offset - 4, specific_tree, access);

		if (ami->generic_mapping)
			map_generic_access(&access, ami->generic_mapping);

		if (ami->standard_mapping)
			map_standard_access(&access, ami->standard_mapping);

		if (access != mapped_access) {
			ami->specific_rights_fn(
				tvb, offset - 4, specific_mapped,
				mapped_access);
		}

		return offset;
	}

	proto_tree_add_bitmask_list_value(specific_tree, tvb, offset - 4, 4, access_specific_flags, access);

	return offset;
}

static int hf_nt_access_mask;

#define ACL_REVISION_NT4		2
#define ACL_REVISION_ADS		4
static const value_string acl_revision_vals[] = {
	{ ACL_REVISION_NT4,	"NT4"},
	{ ACL_REVISION_ADS,	"AD"},
	{0,NULL}
};

#define ACE_TYPE_ACCESS_ALLOWED		0
#define ACE_TYPE_ACCESS_DENIED		1
#define ACE_TYPE_SYSTEM_AUDIT		2
#define ACE_TYPE_SYSTEM_ALARM		3
#define ACE_TYPE_ALLOWED_COMPOUND	4
#define ACE_TYPE_ACCESS_ALLOWED_OBJECT	5
#define ACE_TYPE_ACCESS_DENIED_OBJECT	6
#define ACE_TYPE_SYSTEM_AUDIT_OBJECT	7
#define ACE_TYPE_SYSTEM_ALARM_OBJECT	8
#define ACE_TYPE_ACCESS_ALLOWED_CALLBACK         9
#define ACE_TYPE_ACCESS_DENIED_CALLBACK         10
#define ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT 11
#define ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT  12
#define ACE_TYPE_SYSTEM_AUDIT_CALLBACK          13
#define ACE_TYPE_SYSTEM_ALARM_CALLBACK          14
#define ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT   15
#define ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT   16
#define ACE_TYPE_SYSTEM_MANDATORY_LABEL         17
#define ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE      18
#define ACE_TYPE_SYSTEM_SCOPED_POLICY_ID        19

static const value_string ace_type_vals[] = {
	{ ACE_TYPE_ACCESS_ALLOWED,		   "Access Allowed"},
	{ ACE_TYPE_ACCESS_DENIED,		   "Access Denied"},
	{ ACE_TYPE_SYSTEM_AUDIT,		   "System Audit"},
	{ ACE_TYPE_SYSTEM_ALARM,		   "System Alarm"},
	{ ACE_TYPE_ALLOWED_COMPOUND,		   "Allowed Compound"},
	{ ACE_TYPE_ACCESS_ALLOWED_OBJECT,	   "Allowed Object"},
	{ ACE_TYPE_ACCESS_DENIED_OBJECT,	   "Denied Object"},
	{ ACE_TYPE_SYSTEM_AUDIT_OBJECT,		   "Audit Object"},
	{ ACE_TYPE_SYSTEM_ALARM_OBJECT,		   "Alarm Object"},
	{ ACE_TYPE_ACCESS_ALLOWED_CALLBACK,        "Allowed Callback"},
	{ ACE_TYPE_ACCESS_DENIED_CALLBACK,         "Denied Callback"},
	{ ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT, "Allowed Callback Object"},
	{ ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT,  "Denied Callback Object"},
	{ ACE_TYPE_SYSTEM_AUDIT_CALLBACK,          "Audit Callback"},
	{ ACE_TYPE_SYSTEM_ALARM_CALLBACK,          "Alarm Callback"},
	{ ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT,   "Audit Callback Object"},
	{ ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT,   "Alarm Callback Object"},
	{ ACE_TYPE_SYSTEM_MANDATORY_LABEL,         "Mandatory label"},
	{ ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE,      "Resource Attribute"},
	{ ACE_TYPE_SYSTEM_SCOPED_POLICY_ID,        "Scoped Policy ID" },
	{ 0, NULL}
};
static const true_false_string tfs_ace_flags_object_inherit = {
	"Subordinate files will inherit this ACE",
	"Subordinate files will not inherit this ACE"
};
static const true_false_string tfs_ace_flags_container_inherit = {
	"Subordinate containers will inherit this ACE",
	"Subordinate containers will not inherit this ACE"
};
static const true_false_string tfs_ace_flags_non_propagate_inherit = {
	"Subordinate object will not propagate the inherited ACE further",
	"Subordinate object will propagate the inherited ACE further"
};
static const true_false_string tfs_ace_flags_inherit_only = {
	"This ACE does not apply to the current object",
	"This ACE applies to the current object"
};
static const true_false_string tfs_ace_flags_inherited_ace = {
	"This ACE was inherited from its parent object",
	"This ACE was not inherited from its parent object"
};
static const true_false_string tfs_ace_flags_successful_access = {
	"Successful accesses will be audited",
	"Successful accesses will not be audited"
};
static const true_false_string tfs_ace_flags_failed_access = {
	"Failed accesses will be audited",
	"Failed accesses will not be audited"
};

static const true_false_string flags_sec_info_sacl = {
	"Request SACL",
	"Do NOT request SACL"
};
static const true_false_string flags_sec_info_dacl = {
	"Request DACL",
	"Do NOT request DACL"
};
static const true_false_string flags_sec_info_group = {
	"Request GROUP",
	"Do NOT request group"
};
static const true_false_string flags_sec_info_owner = {
	"Request OWNER",
	"Do NOT request owner"
};

static const true_false_string flags_ace_sra_info_manual = {
	"Manually Assigned",
	"NOT Manually Assigned"
};


static const true_false_string flags_ace_sra_info_policy_derived = {
	"Policy Derived",
	"NOT Policy Derived"
};

static const true_false_string flags_ace_sra_info_non_inheritable = {
	"Non-Inheritable",
	"Inheritable"
};

static const true_false_string flags_ace_sra_info_case_sensitive = {
	"Case Sensitive",
	"NOT Case Sensitive"
};

static const true_false_string flags_ace_sra_info_deny_only = {
	"Deny Only",
	"NOT Deny Only"
};

static const true_false_string flags_ace_sra_info_disabled_by_default = {
	"Disabled By Default",
	"NOT Disabled By Default"
};

static const true_false_string flags_ace_sra_info_disabled = {
	"Disabled",
	"NOT Disabled"
};

static const true_false_string flags_ace_sra_info_mandatory = {
	"Mandatory",
	"NOT Mandatory"
};

#define APPEND_ACE_TEXT(flag, item, string) \
	if(flag){							\
		if(item)						\
			proto_item_append_text(item, string, sep);	\
		sep = ", ";						\
	}


static int
dissect_nt_ace_object(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
{
	proto_item *item;
	proto_tree *tree;
	proto_item *flags_item;
	uint32_t flags;
	int old_offset=offset;
	const char *sep = " ";
	static int * const ace_flags[] = {
		&hf_nt_ace_flags_object_type_present,
		&hf_nt_ace_flags_inherited_object_type_present,
		NULL
	};

	tree = proto_tree_add_subtree(parent_tree, tvb, offset, 0,
					   ett_nt_ace_object, &item, "ACE Object");

	/* flags */
	flags=tvb_get_letohl(tvb, offset);
	flags_item = proto_tree_add_bitmask(tree, tvb, offset, hf_nt_ace_flags_object,
					   ett_nt_ace_object_flags, ace_flags, ENC_LITTLE_ENDIAN);

	APPEND_ACE_TEXT(flags&0x00000001, flags_item, "%sObject Type Present");
	APPEND_ACE_TEXT(flags&0x00000002, flags_item, "%sInherited Object Type Present");
	offset+=4;


	/* is there a GUID ? */
	if(flags&0x00000001){
		proto_tree_add_item(tree, hf_nt_ace_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
		offset+=16;
	}

	/* is there an inherited GUID ? */
	if(flags&0x00000002){
		proto_tree_add_item(tree, hf_nt_ace_inherited_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
		offset+=16;
	}

	proto_item_set_len(item, offset-old_offset);
	return offset;
}

static int
dissect_nt_v2_ace_flags(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
			uint8_t *data)
{
	proto_item *item = NULL;
	uint8_t mask;
	const char *sep = " ";
	static int * const ace_flags[] = {
		&hf_nt_ace_flags_failed_access,
		&hf_nt_ace_flags_successful_access,
		&hf_nt_ace_flags_inherited_ace,
		&hf_nt_ace_flags_inherit_only,
		&hf_nt_ace_flags_non_propagate_inherit,
		&hf_nt_ace_flags_container_inherit,
		&hf_nt_ace_flags_object_inherit,
		NULL
	};

	mask = tvb_get_uint8(tvb, offset);

	if (data)
		*data = mask;

	item = proto_tree_add_bitmask(parent_tree, tvb, offset, hf_nt_ace_flags,
					   ett_nt_ace_flags, ace_flags, ENC_NA);

	APPEND_ACE_TEXT(mask&0x80, item, "%sFailed Access");
	APPEND_ACE_TEXT(mask&0x40, item, "%sSuccessful Access");
	APPEND_ACE_TEXT(mask&0x10, item, "%sInherited ACE");
	APPEND_ACE_TEXT(mask&0x08, item, "%sInherit Only");
	APPEND_ACE_TEXT(mask&0x04, item, "%sNo Propagate Inherit");
	APPEND_ACE_TEXT(mask&0x02, item, "%sContainer Inherit");
	APPEND_ACE_TEXT(mask&0x01, item, "%sObject Inherit");


	offset += 1;
	return offset;
}

static int
dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
		  proto_tree *parent_tree, uint8_t *drep,
		  struct access_mask_info *ami)
{
	proto_item *item;
	proto_tree *tree;
	int old_offset = offset;
	char *sid_str = NULL;
	uint16_t size;
	uint16_t data_size;
	uint8_t type;
	uint8_t flags;
	uint32_t perms = 0;

	tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1,
					   ett_nt_ace, &item, "NT ACE: ");

	/* type */
	type = tvb_get_uint8(tvb, offset);
	proto_tree_add_uint(tree, hf_nt_ace_type, tvb, offset, 1, type);
	offset += 1;

	/* flags */
	offset = dissect_nt_v2_ace_flags(tvb, offset, tree, &flags);

	/* size */
	size = tvb_get_letohs(tvb, offset);
	if (size < 4) {
		/*
		 * BOGUS - the size includes the ACE header length,
		 * which is 4.
		 */
		proto_tree_add_uint_format_value(tree, hf_nt_ace_size, tvb, offset, 2,
		    size, "%u (bogus, must be >= 4)", size);
		return old_offset;	/* our caller quits in this case */
	}
	proto_tree_add_uint(tree, hf_nt_ace_size, tvb, offset, 2, size);
	offset += 2;

	/* some ACE types we not yet handle store other things than access mask
	 * and SID in here.
	 * sometimes things that are not related at all to access control.
	 *    naughty naughty.    -- ronnie
	 */
	switch(type){
	case ACE_TYPE_ACCESS_ALLOWED:
	case ACE_TYPE_ACCESS_DENIED:
	case ACE_TYPE_SYSTEM_AUDIT:
	case ACE_TYPE_SYSTEM_ALARM:
	case ACE_TYPE_ALLOWED_COMPOUND:
	case ACE_TYPE_ACCESS_ALLOWED_OBJECT:
	case ACE_TYPE_ACCESS_DENIED_OBJECT:
	case ACE_TYPE_SYSTEM_AUDIT_OBJECT:
	case ACE_TYPE_SYSTEM_ALARM_OBJECT:
	case ACE_TYPE_ACCESS_ALLOWED_CALLBACK:
	case ACE_TYPE_ACCESS_DENIED_CALLBACK:
	case ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT:
	case ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT:
	case ACE_TYPE_SYSTEM_AUDIT_CALLBACK:
	case ACE_TYPE_SYSTEM_ALARM_CALLBACK:
	case ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT:
	case ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT:
	case ACE_TYPE_SYSTEM_MANDATORY_LABEL:
	case ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE:
	case ACE_TYPE_SYSTEM_SCOPED_POLICY_ID:
		/* access mask */
		offset = dissect_nt_access_mask(
			tvb, offset, pinfo, tree, NULL, drep,
			hf_nt_access_mask, ami, &perms);

		/* these aces contain an extra object */
		switch(type){
		case ACE_TYPE_ACCESS_ALLOWED_OBJECT:
		case ACE_TYPE_ACCESS_DENIED_OBJECT:
		case ACE_TYPE_SYSTEM_AUDIT_OBJECT:
		case ACE_TYPE_SYSTEM_ALARM_OBJECT:
		case ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT:
		case ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT:
		case ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT:
		case ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT:
			offset=dissect_nt_ace_object(tvb, offset, tree);
		}

		/* SID */
		offset = dissect_nt_sid(tvb, offset, tree, "SID", &sid_str, -1);

		if (item)
			proto_item_append_text(
				item, "%s, flags 0x%02x, %s, mask 0x%08x", sid_str, flags,
				val_to_str(type, ace_type_vals, "Unknown ACE type (0x%02x)"),
				perms);

		data_size = size - (offset - old_offset);

		/* Dissect Dynamic Access Control related ACE types
		   (if present). That is, Conditional ACE and Resource
		   Attributes. See [MS-DTYP] v20180912 section 2.4.4.17 */
		switch (type) {
		    case ACE_TYPE_ACCESS_ALLOWED_CALLBACK:
		    case ACE_TYPE_ACCESS_DENIED_CALLBACK:
		    case ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT:
		    case ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT:
		    case ACE_TYPE_SYSTEM_AUDIT_CALLBACK:
		    case ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT:
			dissect_nt_conditional_ace(tvb, pinfo, offset, data_size, tree);
			break;

		    case ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE:
			dissect_nt_ace_system_resource_attribute(tvb, offset, data_size, tree);
			break;
		}
		break;
	};

	proto_item_set_len(item, offset-old_offset);

	/* Sometimes there is some spare space at the end of the ACE so use
	   the size field to work out where the end is. */

	return old_offset + size;
}

static int
dissect_nt_acl(tvbuff_t *tvb, int offset_a, packet_info *pinfo,
	       proto_tree *parent_tree, uint8_t *drep, const char *name,
	       struct access_mask_info *ami)
{
	proto_item *item;
	proto_tree *tree;
	int old_offset = offset_a;
	int pre_ace_offset;
	uint16_t revision;
	uint32_t num_aces;
	volatile int offset_v = offset_a;
	volatile bool missing_data = false;
	volatile bool bad_ace = false;

	tree = proto_tree_add_subtree_format(parent_tree, tvb, offset_v, -1,
					   ett_nt_acl, &item, "NT %s ACL", name);

	/* revision */
	/*
	 * XXX - is this *really* 2 bytes?  The page at
	 *
	 *	https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_acl
	 *
	 * indicates that it's one byte of revision and one byte of
	 * zero padding, which means the code that used to be here
	 * was correct - and this code would give the same results
	 * as long as the padding is zero, so if this dissects it
	 * correctly when the padding is zero, and the padding is
	 * always zero, the old code would dissect it correctly
	 * also.
	 */
	revision = tvb_get_letohs(tvb, offset_v);
	proto_tree_add_uint(tree, hf_nt_acl_revision,
		tvb, offset_v, 2, revision);
	offset_v += 2;

	switch(revision){
	case ACL_REVISION_NT4:
	case ACL_REVISION_ADS:
	case 3:  /* weirdo type */
	  /* size */
	  proto_tree_add_item(tree, hf_nt_acl_size, tvb, offset_v, 2, ENC_LITTLE_ENDIAN);
	  offset_v += 2;

	  /* number of ace structures */
	  /*
	   * XXX - is this *really* 4 bytes?  The page referred to above
	   * says it's 2 bytes of count followed by two bytes of
	   * zero padding.
	   */
	  num_aces = tvb_get_letohl(tvb, offset_v);
	  proto_tree_add_uint(tree, hf_nt_acl_num_aces,
			      tvb, offset_v, 4, num_aces);
	  offset_v += 4;

	  while(num_aces-- && !missing_data && !bad_ace) {
		pre_ace_offset = offset_v;

		/*
		 * These are at an offset_v later in the packet; don't
		 * fail if we can't fetch them, just note the problem
		 * and dissect the stuff before it.
		 */
		TRY {
		  offset_v = dissect_nt_v2_ace(tvb, offset_v, pinfo, tree, drep, ami);
		  if (pre_ace_offset == offset_v) {
			/*
			 * Bogus ACE, with a length < 4.
			 */
			bad_ace = true;
		  }
		}

		CATCH(ContainedBoundsError) {
			proto_tree_add_expert(tree, pinfo, &ei_nt_ace_extends_beyond_data, tvb, offset_v, 0);
			missing_data = true;
		}

		CATCH(ReportedBoundsError) {
			proto_tree_add_expert(tree, pinfo, &ei_nt_ace_extends_beyond_reassembled_data, tvb, offset_v, 0);
			missing_data = true;
		}

		ENDTRY;
	  }
	}

	proto_item_set_len(item, offset_v-old_offset);
	return offset_v;
}

static const true_false_string tfs_sec_desc_type_owner_defaulted = {
	"OWNER is DEFAULTED",
	"Owner is NOT defaulted"
};
static const true_false_string tfs_sec_desc_type_group_defaulted = {
	"GROUP is DEFAULTED",
	"Group is NOT defaulted"
};
static const true_false_string tfs_sec_desc_type_dacl_present = {
	"DACL is PRESENT",
	"DACL is NOT present"
};
static const true_false_string tfs_sec_desc_type_dacl_defaulted = {
	"DACL is DEFAULTED",
	"DACL is NOT defaulted"
};
static const true_false_string tfs_sec_desc_type_sacl_present = {
	"SACL is PRESENT",
	"SACL is NOT present"
};
static const true_false_string tfs_sec_desc_type_sacl_defaulted = {
	"SACL is DEFAULTED",
	"SACL is NOT defaulted"
};
static const true_false_string tfs_sec_desc_type_dacl_trusted = {
	"DACL TRUSTED is TRUE",
	"Dacl trusted is FALSE"
};
static const true_false_string tfs_sec_desc_type_server_security = {
	"SERVER SECURITY is TRUE",
	"Server security is FALSE"
};
static const true_false_string tfs_sec_desc_type_dacl_auto_inherit_req = {
	"DACL has AUTO INHERIT REQUIRED",
	"DACL does NOT require auto inherit"
};
static const true_false_string tfs_sec_desc_type_sacl_auto_inherit_req = {
	"SACL has AUTO INHERIT REQUIRED",
	"SACL does NOT require auto inherit"
};
static const true_false_string tfs_sec_desc_type_dacl_auto_inherited = {
	"DACL is AUTO INHERITED",
	"DACL is NOT auto inherited"
};
static const true_false_string tfs_sec_desc_type_sacl_auto_inherited = {
	"SACL is AUTO INHERITED",
	"SACL is NOT auto inherited"
};
static const true_false_string tfs_sec_desc_type_dacl_protected = {
	"The DACL is PROTECTED",
	"The DACL is NOT protected"
};
static const true_false_string tfs_sec_desc_type_sacl_protected = {
	"The SACL is PROTECTED",
	"The SACL is NOT protected"
};
static const true_false_string tfs_sec_desc_type_rm_control_valid = {
	"Rm control valid is TRUE",
	"Rm control valid is FALSE"
};
static const true_false_string tfs_sec_desc_type_self_relative = {
	"This SecDesc is SELF RELATIVE",
	"This SecDesc is NOT self relative"
};


static int
dissect_nt_sec_desc_type(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
{
	static int * const flags[] = {
		&hf_nt_sec_desc_type_self_relative,
		&hf_nt_sec_desc_type_rm_control_valid,
		&hf_nt_sec_desc_type_sacl_protected,
		&hf_nt_sec_desc_type_dacl_protected,
		&hf_nt_sec_desc_type_sacl_auto_inherited,
		&hf_nt_sec_desc_type_dacl_auto_inherited,
		&hf_nt_sec_desc_type_sacl_auto_inherit_req,
		&hf_nt_sec_desc_type_dacl_auto_inherit_req,
		&hf_nt_sec_desc_type_server_security,
		&hf_nt_sec_desc_type_dacl_trusted,
		&hf_nt_sec_desc_type_sacl_defaulted,
		&hf_nt_sec_desc_type_sacl_present,
		&hf_nt_sec_desc_type_dacl_defaulted,
		&hf_nt_sec_desc_type_dacl_present,
		&hf_nt_sec_desc_type_group_defaulted,
		&hf_nt_sec_desc_type_owner_defaulted,
		NULL
	};

	proto_tree_add_bitmask(parent_tree, tvb, offset, hf_nt_sec_desc_type,
					   ett_nt_sec_desc_type, flags, ENC_LITTLE_ENDIAN);

	offset += 2;
	return offset;
}

int
dissect_nt_security_information(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
{
	proto_item *item = NULL;
	uint32_t mask;
	static int * const flags[] = {
		&hf_nt_security_information_sacl,
		&hf_nt_security_information_dacl,
		&hf_nt_security_information_group,
		&hf_nt_security_information_owner,
		NULL
	};

	mask = tvb_get_letohl(tvb, offset);
	item = proto_tree_add_bitmask(parent_tree, tvb, offset, hf_nt_security_information,
					   ett_nt_security_information, flags, ENC_LITTLE_ENDIAN);

	if (mask & 0x00000008) {
		proto_item_append_text(item, " SACL");
	}
	if (mask & 0x00000004) {
		proto_item_append_text(item, " DACL");
	}
	if (mask & 0x00000002) {
		proto_item_append_text(item, " GROUP");
	}
	if (mask & 0x00000001) {
		proto_item_append_text(item, " OWNER");
	}

	offset += 4;

	return offset;
}

int
dissect_nt_sec_desc(tvbuff_t *tvb, int offset_a, packet_info *pinfo,
		    proto_tree *parent_tree, uint8_t *drep,
		    bool len_supplied _U_, int len,
		    struct access_mask_info *ami)
{
	proto_item *item = NULL;
	proto_tree * volatile tree = NULL;
	uint16_t revision;
	int start_offset = offset_a;
	volatile int offset_v=offset_a;
	volatile int end_offset;
	volatile int item_offset;
	uint32_t owner_sid_offset;
	proto_item *it_owner_sid_offs = NULL;
	volatile uint32_t group_sid_offset;
	proto_item * volatile it_gr_sid_offs = NULL;
	volatile uint32_t sacl_offset;
	proto_item * volatile it_sacl_offs = NULL;
	volatile uint32_t dacl_offset;
	proto_item * volatile it_dacl_offs = NULL;

	tree = proto_tree_add_subtree(parent_tree, tvb, offset_v, -1,
				   ett_nt_sec_desc, &item, "NT Security Descriptor");

	/* revision */
	revision = tvb_get_letohs(tvb, offset_v);
	proto_tree_add_uint(tree, hf_nt_sec_desc_revision,
		tvb, offset_v, 2, revision);
	offset_v += 2;

	switch(revision){
	case 1:  /* only version we will ever see of this structure?*/
	  /* type */
	  offset_v = dissect_nt_sec_desc_type(tvb, offset_v, tree);

	  /* offset_v to owner sid */
	  owner_sid_offset = tvb_get_letohl(tvb, offset_v);
	  if(owner_sid_offset != 0 && owner_sid_offset < 20){
	    /* Bogus value - points into fixed portion of descriptor */
	    proto_tree_add_uint_format_value(tree, hf_nt_offset_to_owner_sid, tvb, offset_v, 4, owner_sid_offset, "%u (bogus, must be >= 20)", owner_sid_offset);
	    owner_sid_offset = 0;
	  } else
	    it_owner_sid_offs = proto_tree_add_item(tree, hf_nt_offset_to_owner_sid, tvb, offset_v, 4, ENC_LITTLE_ENDIAN);
	  offset_v += 4;

	  /* offset to group sid */
	  group_sid_offset = tvb_get_letohl(tvb, offset_v);
	  if(group_sid_offset != 0 && group_sid_offset < 20){
	    /* Bogus value - points into fixed portion of descriptor */
	    proto_tree_add_uint_format_value(tree, hf_nt_offset_to_group_sid, tvb, offset_v, 4, group_sid_offset, "%u (bogus, must be >= 20)", group_sid_offset);
	    group_sid_offset = 0;
	  } else
	    it_gr_sid_offs = proto_tree_add_item(tree, hf_nt_offset_to_group_sid, tvb, offset_v, 4, ENC_LITTLE_ENDIAN);
	  offset_v += 4;

	  /* offset to sacl */
	  sacl_offset = tvb_get_letohl(tvb, offset_v);
	  if(sacl_offset != 0 && sacl_offset < 20){
	    /* Bogus value - points into fixed portion of descriptor */
	    proto_tree_add_uint_format_value(tree, hf_nt_offset_to_sacl, tvb, offset_v, 4, sacl_offset, "%u (bogus, must be >= 20)", sacl_offset);
	    sacl_offset = 0;
	  } else
	    it_sacl_offs = proto_tree_add_item(tree, hf_nt_offset_to_sacl, tvb, offset_v, 4, ENC_LITTLE_ENDIAN);
	  offset_v += 4;

	  /* offset to dacl */
	  dacl_offset = tvb_get_letohl(tvb, offset_v);
	  if(dacl_offset != 0 && dacl_offset < 20){
	    /* Bogus value - points into fixed portion of descriptor */
	    proto_tree_add_uint_format_value(tree, hf_nt_offset_to_dacl, tvb, offset_v, 4, dacl_offset, "%u (bogus, must be >= 20)", dacl_offset);
	    dacl_offset = 0;
	  } else
	    it_dacl_offs = proto_tree_add_item(tree, hf_nt_offset_to_dacl, tvb, offset_v, 4, ENC_LITTLE_ENDIAN);
	  offset_v += 4;

	  end_offset = offset_v;

	  /*owner SID*/
	  if(owner_sid_offset){
	    item_offset = start_offset+owner_sid_offset;
	    if (item_offset < start_offset) {
		    expert_add_info(pinfo, it_owner_sid_offs,
				    &ei_nt_item_offs_out_of_range);
		    break;
	    }
	    TRY{
	      offset_v = dissect_nt_sid(tvb, item_offset, tree, "Owner", NULL, -1);
	      if (offset_v > end_offset)
	        end_offset = offset_v;
	    }

	    CATCH(ContainedBoundsError) {
	      proto_tree_add_expert(tree, pinfo, &ei_nt_owner_sid_beyond_data, tvb, item_offset, 0);
	    }

	    CATCH(ReportedBoundsError) {
	      proto_tree_add_expert(tree, pinfo, &ei_nt_owner_sid_beyond_reassembled_data, tvb, item_offset, 0);
	    }

	    ENDTRY;
	  }

	  /*group SID*/
	  if(group_sid_offset){
	    item_offset = start_offset+group_sid_offset;
	    if (item_offset < start_offset) {
		    expert_add_info(pinfo, it_gr_sid_offs,
				    &ei_nt_item_offs_out_of_range);
		    break;
	    }
	    TRY {
	      offset_v = dissect_nt_sid(tvb, item_offset, tree, "Group", NULL, -1);
	      if (offset_v > end_offset)
	        end_offset = offset_v;
	    }

	    CATCH(ContainedBoundsError) {
	      proto_tree_add_expert(tree, pinfo, &ei_nt_group_sid_beyond_data, tvb, item_offset, 0);
	    }

	    CATCH(ReportedBoundsError) {
	      proto_tree_add_expert(tree, pinfo, &ei_nt_group_sid_beyond_reassembled_data, tvb, item_offset, 0);
	    }

	    ENDTRY;
	  }

	  /* sacl */
	  if(sacl_offset){
	    item_offset = start_offset+sacl_offset;
	    if (item_offset < start_offset) {
		    expert_add_info(pinfo, it_sacl_offs,
				    &ei_nt_item_offs_out_of_range);
		    break;
	    }
	    offset_v = dissect_nt_acl(tvb, item_offset, pinfo, tree,
				    drep, "System (SACL)", ami);
	    if (offset_v > end_offset)
	      end_offset = offset_v;
	  }

	  /* dacl */
	  if(dacl_offset){
	    item_offset = start_offset+dacl_offset;
	    if (item_offset < start_offset) {
		    expert_add_info(pinfo, it_dacl_offs,
				    &ei_nt_item_offs_out_of_range);
		    break;
	    }
	    offset_v = dissect_nt_acl(tvb, item_offset, pinfo, tree,
				    drep, "User (DACL)", ami);
	    if (offset_v > end_offset)
	      end_offset = offset_v;
	  }

	  break;

	default:
	  end_offset = offset_v;
	  break;
	}

	len = end_offset - start_offset;
	proto_item_set_len(item, len);

	return offset_v;
}

/*
 * XXX - we should have a way to register fields not associated with a
 * protocol.
 *
 * XXX - make-reg-dotc.py doesn't check for an argument list of "(void)",
 * so we have to give this a name other than "proto_register_..." so that
 * it doesn't end up being called from "register.c".
 */
void
proto_do_register_windows_common(int proto_smb)
{
	static hf_register_info hf[] = {
		/* Security descriptors */

		{ &hf_nt_sec_desc_revision,
		  { "Revision", "nt.sec_desc.revision", FT_UINT16, BASE_DEC,
		    NULL, 0, "Version of NT Security Descriptor structure", HFILL }},

		{ &hf_nt_sec_desc_type_owner_defaulted,
		  { "Owner Defaulted", "nt.sec_desc.type.owner_defaulted", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_owner_defaulted), 0x0001, "Is Owner Defaulted set?", HFILL }},

		{ &hf_nt_sec_desc_type_group_defaulted,
		  { "Group Defaulted", "nt.sec_desc.type.group_defaulted", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_group_defaulted), 0x0002, "Is Group Defaulted?", HFILL }},

		{ &hf_nt_sec_desc_type_dacl_present,
		  { "DACL Present", "nt.sec_desc.type.dacl_present", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_dacl_present), 0x0004, "Does this SecDesc have DACL present?", HFILL }},

		{ &hf_nt_sec_desc_type_dacl_defaulted,
		  { "DACL Defaulted", "nt.sec_desc.type.dacl_defaulted", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_dacl_defaulted), 0x0008, "Does this SecDesc have DACL Defaulted?", HFILL }},

		{ &hf_nt_sec_desc_type_sacl_present,
		  { "SACL Present", "nt.sec_desc.type.sacl_present", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_sacl_present), 0x0010, "Is the SACL present?", HFILL }},

		{ &hf_nt_sec_desc_type_sacl_defaulted,
		  { "SACL Defaulted", "nt.sec_desc.type.sacl_defaulted", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_sacl_defaulted), 0x0020, "Does this SecDesc have SACL Defaulted?", HFILL }},

		{ &hf_nt_sec_desc_type_dacl_auto_inherit_req,
		  { "DACL Auto Inherit Required", "nt.sec_desc.type.dacl_auto_inherit_req", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_dacl_auto_inherit_req), 0x0100, "Does this SecDesc have DACL Auto Inherit Required set?", HFILL }},

		{ &hf_nt_sec_desc_type_dacl_trusted,
		  { "DACL Trusted", "nt.sec_desc.type.dacl_trusted", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_dacl_trusted), 0x0040, "Does this SecDesc have DACL TRUSTED set?", HFILL }},

		{ &hf_nt_sec_desc_type_server_security,
		  { "Server Security", "nt.sec_desc.type.server_security", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_server_security), 0x0080, "Does this SecDesc have SERVER SECURITY set?", HFILL }},

		{ &hf_nt_sec_desc_type_sacl_auto_inherit_req,
		  { "SACL Auto Inherit Required", "nt.sec_desc.type.sacl_auto_inherit_req", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_sacl_auto_inherit_req), 0x0200, "Does this SecDesc have SACL Auto Inherit Required set?", HFILL }},

		{ &hf_nt_sec_desc_type_dacl_auto_inherited,
		  { "DACL Auto Inherited", "nt.sec_desc.type.dacl_auto_inherited", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_dacl_auto_inherited), 0x0400, "Is this DACL auto inherited", HFILL }},

		{ &hf_nt_sec_desc_type_sacl_auto_inherited,
		  { "SACL Auto Inherited", "nt.sec_desc.type.sacl_auto_inherited", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_sacl_auto_inherited), 0x0800, "Is this SACL auto inherited", HFILL }},

		{ &hf_nt_sec_desc_type_dacl_protected,
		  { "DACL Protected", "nt.sec_desc.type.dacl_protected", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_dacl_protected), 0x1000, "Is the DACL structure protected?", HFILL }},

		{ &hf_nt_sec_desc_type_sacl_protected,
		  { "SACL Protected", "nt.sec_desc.type.sacl_protected", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_sacl_protected), 0x2000, "Is the SACL structure protected?", HFILL }},

		{ &hf_nt_sec_desc_type_self_relative,
		  { "Self Relative", "nt.sec_desc.type.self_relative", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_self_relative), 0x8000, "Is this SecDesc self relative?", HFILL }},

		{ &hf_nt_sec_desc_type_rm_control_valid,
		  { "RM Control Valid", "nt.sec_desc.type.rm_control_valid", FT_BOOLEAN, 16,
		    TFS(&tfs_sec_desc_type_rm_control_valid), 0x4000, "Is RM Control Valid set?", HFILL }},

		/* SIDs */

		{ &hf_nt_sid,
		  { "SID", "nt.sid", FT_STRING, BASE_NONE,
		    NULL, 0, "SID: Security Identifier", HFILL }},

		{ &hf_nt_sid_revision,
		  { "Revision", "nt.sid.revision", FT_UINT8, BASE_DEC,
		    NULL, 0, "Version of SID structure", HFILL }},

		{ &hf_nt_sid_num_auth,
		  { "Num Auth", "nt.sid.num_auth", FT_UINT8, BASE_DEC,
		    NULL, 0, "Number of authorities for this SID", HFILL }},

		{ &hf_nt_sid_auth_dec,
		  { "Authority", "nt.sid.auth", FT_UINT64, BASE_DEC,
		    NULL, 0, "Identifier Authority", HFILL }},

		{ &hf_nt_sid_auth_hex,
		  { "Authority", "nt.sid.auth", FT_UINT64, BASE_HEX,
		    NULL, 0, "Identifier Authority", HFILL }},

		{ &hf_nt_sid_subauth,
		  { "Subauthorities", "nt.sid.subauth", FT_STRING, BASE_NONE,
		  NULL, 0, "Subauthorities fields", HFILL }},

		{ &hf_nt_sid_rid_dec,
		  { "RID", "nt.sid.rid", FT_UINT32, BASE_DEC,
		  NULL, 0, "Relative IDentifier: identifies a user or group", HFILL }},

		{ &hf_nt_sid_rid_hex,
		  { "RID", "nt.sid.rid", FT_UINT32, BASE_HEX,
		  NULL, 0, "Relative IDentifier: identifies a user or group", HFILL }},

		{ &hf_nt_sid_wkwn,
		  { "Well-known SID", "nt.sid.wkwn", FT_STRING, BASE_NONE,
		  NULL, 0, NULL, HFILL }},

		{ &hf_nt_sid_domain,
		  { "Domain", "nt.sid.domain", FT_STRING, BASE_NONE,
		  NULL, 0, NULL, HFILL }},

		/* ACLs */

		{ &hf_nt_acl_revision,
		  { "Revision", "nt.acl.revision", FT_UINT16, BASE_DEC,
		    VALS(acl_revision_vals), 0, "Version of NT ACL structure", HFILL }},

		{ &hf_nt_acl_size,
		  { "Size", "nt.acl.size", FT_UINT16, BASE_DEC,
		    NULL, 0, "Size of NT ACL structure", HFILL }},

		{ &hf_nt_acl_num_aces,
		  { "Num ACEs", "nt.acl.num_aces", FT_UINT32, BASE_DEC,
		    NULL, 0, "Number of ACE structures for this ACL", HFILL }},

		/* ACEs */

		{ &hf_nt_ace_type,
		  { "Type", "nt.ace.type",
		    FT_UINT8, BASE_DEC, VALS(ace_type_vals), 0, "Type of ACE",
		    HFILL }},

		{ &hf_nt_ace_size,
		  { "Size", "nt.ace.size", FT_UINT16, BASE_DEC, NULL, 0,
		    "Size of this ACE", HFILL }},

		{ &hf_nt_ace_flags_object_inherit,
		  { "Object Inherit", "nt.ace.flags.object_inherit", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_object_inherit), 0x01, "Will subordinate files inherit this ACE?", HFILL }},

		{ &hf_nt_ace_flags_container_inherit,
		  { "Container Inherit", "nt.ace.flags.container_inherit", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_container_inherit), 0x02, "Will subordinate containers inherit this ACE?", HFILL }},

		{ &hf_nt_ace_flags_non_propagate_inherit,
		  { "Non-Propagate Inherit", "nt.ace.flags.non_propagate_inherit", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_non_propagate_inherit), 0x04, "Will subordinate object propagate this ACE further?", HFILL }},

		{ &hf_nt_ace_flags_inherit_only,
		  { "Inherit Only", "nt.ace.flags.inherit_only", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_inherit_only), 0x08, "Does this ACE apply to the current object?", HFILL }},

		{ &hf_nt_ace_flags_inherited_ace,
		  { "Inherited ACE", "nt.ace.flags.inherited_ace", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_inherited_ace), 0x10, "Was this ACE inherited from its parent object?", HFILL }},

		{ &hf_nt_ace_flags_successful_access,
		  { "Audit Successful Accesses", "nt.ace.flags.successful_access", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_successful_access), 0x40, "Should successful accesses be audited?", HFILL }},

		{ &hf_nt_ace_flags_failed_access,
		  { "Audit Failed Accesses", "nt.ace.flags.failed_access", FT_BOOLEAN, 8,
		    TFS(&tfs_ace_flags_failed_access), 0x80, "Should failed accesses be audited?", HFILL }},

		/* Access masks */

		{ &hf_nt_access_mask,
		  { "Access required", "nt.access_mask",
		    FT_UINT32, BASE_HEX, NULL, 0x0, "Access mask",
		    HFILL }},

		{ &hf_access_generic_read,
		  { "Generic read", "nt.access_mask.generic_read",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    GENERIC_READ_ACCESS, NULL, HFILL }},

		{ &hf_access_generic_write,
		  { "Generic write", "nt.access_mask.generic_write",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    GENERIC_WRITE_ACCESS, NULL, HFILL }},

		{ &hf_access_generic_execute,
		  { "Generic execute", "nt.access_mask.generic_execute",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    GENERIC_EXECUTE_ACCESS, NULL, HFILL }},

		{ &hf_access_generic_all,
		  { "Generic all", "nt.access_mask.generic_all",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    GENERIC_ALL_ACCESS, NULL, HFILL }},

		{ &hf_access_maximum_allowed,
		  { "Maximum allowed", "nt.access_mask.maximum_allowed",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    MAXIMUM_ALLOWED_ACCESS, NULL, HFILL }},

		{ &hf_access_sacl,
		  { "Access SACL", "nt.access_mask.access_sacl",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    ACCESS_SACL_ACCESS, NULL, HFILL }},

		{ &hf_access_standard_read_control,
		  { "Read control", "nt.access_mask.read_control",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    READ_CONTROL_ACCESS, NULL, HFILL }},

		{ &hf_access_standard_delete,
		  { "Delete", "nt.access_mask.delete",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    DELETE_ACCESS, NULL, HFILL }},

		{ &hf_access_standard_synchronise,
		  { "Synchronise", "nt.access_mask.synchronise",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    SYNCHRONIZE_ACCESS, NULL, HFILL }},

		{ &hf_access_standard_write_dac,
		  { "Write DAC", "nt.access_mask.write_dac",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    WRITE_DAC_ACCESS, NULL, HFILL }},

		{ &hf_access_standard_write_owner,
		  { "Write owner", "nt.access_mask.write_owner",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    WRITE_OWNER_ACCESS, NULL, HFILL }},

		{ &hf_access_specific_15,
		  { "Specific access, bit 15", "nt.access_mask.specific_15",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00008000, NULL, HFILL }},

		{ &hf_access_specific_14,
		  { "Specific access, bit 14", "nt.access_mask.specific_14",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00004000, NULL, HFILL }},

		{ &hf_access_specific_13,
		  { "Specific access, bit 13", "nt.access_mask.specific_13",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00002000, NULL, HFILL }},

		{ &hf_access_specific_12,
		  { "Specific access, bit 12", "nt.access_mask.specific_12",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00001000, NULL, HFILL }},

		{ &hf_access_specific_11,
		  { "Specific access, bit 11", "nt.access_mask.specific_11",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000800, NULL, HFILL }},

		{ &hf_access_specific_10,
		  { "Specific access, bit 10", "nt.access_mask.specific_10",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000400, NULL, HFILL }},

		{ &hf_access_specific_9,
		  { "Specific access, bit 9", "nt.access_mask.specific_9",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000200, NULL, HFILL }},

		{ &hf_access_specific_8,
		  { "Specific access, bit 8", "nt.access_mask.specific_8",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000100, NULL, HFILL }},

		{ &hf_access_specific_7,
		  { "Specific access, bit 7", "nt.access_mask.specific_7",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000080, NULL, HFILL }},

		{ &hf_access_specific_6,
		  { "Specific access, bit 6", "nt.access_mask.specific_6",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
			0x00000040, NULL, HFILL }},

		{ &hf_access_specific_5,
		  { "Specific access, bit 5", "nt.access_mask.specific_5",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000020, NULL, HFILL }},

		{ &hf_access_specific_4,
		  { "Specific access, bit 4", "nt.access_mask.specific_4",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000010, NULL, HFILL }},

		{ &hf_access_specific_3,
		  { "Specific access, bit 3", "nt.access_mask.specific_3",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000008, NULL, HFILL }},

		{ &hf_access_specific_2,
		  { "Specific access, bit 2", "nt.access_mask.specific_2",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000004, NULL, HFILL }},

		{ &hf_access_specific_1,
		  { "Specific access, bit 1", "nt.access_mask.specific_1",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000002, NULL, HFILL }},

		{ &hf_access_specific_0,
		  { "Specific access, bit 0", "nt.access_mask.specific_0",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000001, NULL, HFILL }},

		{ &hf_nt_ace_flags_object_type_present,
		  { "Object Type Present", "nt.ace.object.flags.object_type_present",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000001, NULL, HFILL }},

		{ &hf_nt_ace_flags_inherited_object_type_present,
		  { "Inherited Object Type Present", "nt.ace.object.flags.inherited_object_type_present",
		    FT_BOOLEAN, 32, TFS(&tfs_set_notset),
		    0x00000002, NULL, HFILL }},

	        { &hf_nt_ace_guid,
		  { "GUID", "nt.ace.object.guid", FT_GUID, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

	        { &hf_nt_ace_inherited_guid,
		  { "Inherited GUID", "nt.ace.object.inherited_guid", FT_GUID, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond,
		  { "Conditional Expression", "nt.ace.cond", FT_NONE, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_token,
		  { "Token", "nt.ace.cond.token",
		    FT_UINT8, BASE_HEX, VALS(ace_cond_token_vals), 0, "Type of Token",
		    HFILL }},

		{ &hf_nt_ace_cond_sign,
		  { "SIGN", "nt.ace.cond.sign",
		    FT_UINT8, BASE_HEX, VALS(ace_cond_sign_vals), 0,
		    NULL, HFILL }},

		{ &hf_nt_ace_cond_base,
		  { "BASE", "nt.ace.cond.base",
		    FT_UINT8, BASE_HEX, VALS(ace_cond_base_vals), 0,
		    NULL, HFILL }},

		{ &hf_nt_ace_cond_value_int8,
		  { "INT8", "nt.ace.cond.value_int8", FT_INT8, BASE_DEC,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_value_int16,
		  { "INT16", "nt.ace.cond.value_int16", FT_INT16, BASE_DEC,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_value_int32,
		  { "INT32", "nt.ace.cond.value_int32", FT_INT32, BASE_DEC,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_value_int64,
		  { "INT64", "nt.ace.cond.value_int64", FT_INT64, BASE_DEC,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_value_string,
		  { "UNICODE_STRING", "nt.ace.cond.value_string", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_value_octet_string,
		  { "OCTET_STRING", "nt.ace.cond.value_octet_string", FT_BYTES, BASE_NONE,
		    NULL, 0x0, NULL, HFILL }},

		{ &hf_nt_ace_cond_local_attr,
		  { "LOCAL_ATTRIBUTE", "nt.ace.cond.local_attr", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_user_attr,
		  { "USER_ATTRIBUTE", "nt.ace.cond.user_attr", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_resource_attr,
		  { "RESOURCE_ATTRIBUTE", "nt.ace.cond.resource_attr", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_cond_device_attr,
		  { "DEVICE_ATTRIBUTE", "nt.ace.cond.device_attr", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_sra,
		  { "Resource Attribute", "nt.ace.sra", FT_NONE, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_sra_name_offset,
		  { "Name Offset", "nt.ace.sra.name_offset", FT_UINT32, BASE_DEC, NULL, 0,
		    "Offset to Name of Resource Attribute", HFILL }},

		{ &hf_nt_ace_sra_name,
		  { "Name", "nt.ace.sra.name", FT_STRING, BASE_NONE, NULL, 0,
		    "Name of Resource Attribute", HFILL }},

		{ &hf_nt_ace_sra_type,
		  { "Type", "nt.ace.sra.type",
		    FT_UINT16, BASE_DEC, VALS(ace_sra_type_vals), 0,
		    "Type of Resource Attribute", HFILL }},

		{ &hf_nt_ace_sra_reserved,
		  { "Reserved", "nt.ace.sra.reserved", FT_UINT16, BASE_HEX, NULL, 0,
		    "Reserved of Resource Attribute", HFILL }},

		{ &hf_nt_ace_sra_flags,
		  { "Flags", "nt.ace.sra.flags", FT_UINT32, BASE_HEX, NULL, 0,
		    "Flags of Resource Attribute", HFILL }},

		{ &hf_nt_ace_sra_flags_manual,
		  { "Manual", "nt.ace.sra.flags.manual", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_manual), 0x00010000, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_policy_derived,
		  { "Policy Derived", "nt.ace.sra.flags.policy_derived", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_policy_derived), 0x00020000, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_non_inheritable,
		  { "Non-Inheritable", "nt.ace.sra.flags.non_inheritable", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_non_inheritable), 0x00000001, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_case_sensitive,
		  { "Case Sensitive", "nt.ace.sra.flags.case_sensitive", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_case_sensitive), 0x00000002, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_deny_only,
		  { "Deny Only", "nt.ace.sra.flags.deny_only", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_deny_only), 0x00000004, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_disabled_by_default,
		  { "Disabled By Default", "nt.ace.sra.flags.disabled_by_default", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_disabled_by_default), 0x00000008, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_disabled,
		  { "Disabled", "nt.ace.sra.flags.disabled", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_disabled), 0x00000010, NULL, HFILL }},

		{ &hf_nt_ace_sra_flags_mandatory,
		  { "Mandatory", "nt.ace.sra.flags.mandatory", FT_BOOLEAN, 32,
		    TFS(&flags_ace_sra_info_mandatory), 0x00000020, NULL, HFILL }},

		{ &hf_nt_ace_sra_value_count,
		  { "Value Count", "nt.ace.sra.value_count", FT_UINT32, BASE_DEC, NULL, 0,
		    "Value Count of Resource Attribute", HFILL }},

		{ &hf_nt_ace_sra_value_offset,
		  { "Value Offset", "nt.ace.sra.name_offset", FT_UINT32, BASE_DEC, NULL, 0,
		    "Offset to a Resource Attribute Value", HFILL }},

		{ &hf_nt_ace_sra_value_int64,
		  { "INT64", "nt.ace.sra.value_int64", FT_INT64, BASE_DEC, NULL, 0,
		    NULL, HFILL }},

		{ &hf_nt_ace_sra_value_uint64,
		  { "UINT64", "nt.ace.sra.value_uint64", FT_UINT64, BASE_DEC, NULL, 0,
		    NULL, HFILL }},

		{ &hf_nt_ace_sra_value_string,
		  { "STRING", "nt.ace.sra.value_string", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_sra_value_sid,
		  { "SID", "nt.ace.sra.value_sid", FT_STRING, BASE_NONE,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_sra_value_boolean,
		  { "BOOLEAN", "nt.ace.sra.value_boolean", FT_UINT64, BASE_DEC,
		    NULL, 0, NULL, HFILL }},

		{ &hf_nt_ace_sra_value_octet_string,
		  { "OCTET_STRING", "nt.ace.sra.value_octet_string", FT_BYTES, BASE_NONE,
		    NULL, 0x0, NULL, HFILL }},

		{ &hf_nt_security_information_sacl,
		  { "SACL", "nt.sec_info.sacl", FT_BOOLEAN, 32,
		    TFS(&flags_sec_info_sacl), 0x00000008, NULL, HFILL }},

		{ &hf_nt_security_information_dacl,
		  { "DACL", "nt.sec_info.dacl", FT_BOOLEAN, 32,
		    TFS(&flags_sec_info_dacl), 0x00000004, NULL, HFILL }},

		{ &hf_nt_security_information_group,
		  { "Group", "nt.sec_info.group", FT_BOOLEAN, 32,
		    TFS(&flags_sec_info_group), 0x00000002, NULL, HFILL }},

		{ &hf_nt_security_information_owner,
		  { "Owner", "nt.sec_info.owner", FT_BOOLEAN, 32,
		    TFS(&flags_sec_info_owner), 0x00000001, NULL, HFILL }},

		/* Generated from convert_proto_tree_add_text.pl */
		{ &hf_nt_ace_flags_object, { "ACE Object Flags", "nt.ace.object.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_ace_flags, { "NT ACE Flags", "nt.ace.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_sec_desc_type, { "Type", "nt.sec_desc.type", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_security_information, { "SEC INFO", "nt.sec_info", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_offset_to_owner_sid, { "Offset to owner SID", "nt.offset_to_owner_sid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_offset_to_group_sid, { "Offset to group SID", "nt.offset_to_group_sid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_offset_to_sacl, { "Offset to SACL", "nt.offset_to_sacl", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
		{ &hf_nt_offset_to_dacl, { "Offset to DACL", "nt.offset_to_dacl", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
	};

	static int *ett[] = {
		&ett_nt_sec_desc,
		&ett_nt_sec_desc_type,
		&ett_nt_sid,
		&ett_nt_acl,
		&ett_nt_ace,
		&ett_nt_ace_flags,
		&ett_nt_ace_object,
		&ett_nt_ace_object_flags,
		&ett_nt_access_mask,
		&ett_nt_access_mask_generic,
		&ett_nt_access_mask_standard,
		&ett_nt_access_mask_specific,
		&ett_nt_security_information,
		&ett_nt_ace_cond,
		&ett_nt_ace_cond_data,
		&ett_nt_ace_sra,
		&ett_nt_ace_sra_flags,
		&ett_nt_ace_sra_value_offsets,
		&ett_nt_ace_sra_values,
	};

	static ei_register_info ei[] = {
		{ &ei_nt_ace_extends_beyond_data, { "nt.ace_extends_beyond_data", PI_MALFORMED, PI_ERROR, "ACE Extends beyond end of data", EXPFILL }},
		{ &ei_nt_ace_extends_beyond_reassembled_data, { "nt.ace_extends_beyond_reassembled_data", PI_MALFORMED, PI_ERROR, "ACE Extends beyond end of reassembled data", EXPFILL }},
		{ &ei_nt_owner_sid_beyond_data, { "nt.owner_sid.beyond_data", PI_MALFORMED, PI_ERROR, "Owner SID beyond end of data", EXPFILL }},
		{ &ei_nt_owner_sid_beyond_reassembled_data, { "nt.owner_sid.beyond_reassembled_data", PI_MALFORMED, PI_ERROR, "Owner SID beyond end of reassembled data", EXPFILL }},
		{ &ei_nt_group_sid_beyond_data, { "nt.group_sid.beyond_data", PI_MALFORMED, PI_ERROR, "Group SID beyond end of data", EXPFILL }},
		{ &ei_nt_group_sid_beyond_reassembled_data, { "nt.group_sid.beyond_reassembled_data", PI_MALFORMED, PI_ERROR, "Group SID beyond end of reassembled data", EXPFILL }},
		{ &ei_nt_item_offs_out_of_range, { "nt.item_offset.out_of_range", PI_MALFORMED, PI_ERROR, "Item offset is out of range", EXPFILL }},
	};

	expert_module_t* expert_nt;

	proto_register_subtree_array(ett, array_length(ett));
	proto_register_field_array(proto_smb, hf, array_length(hf));
	expert_nt = expert_register_protocol(proto_smb);
	expert_register_field_array(expert_nt, ei, array_length(ei));
}

/*
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 8
 * tab-width: 8
 * indent-tabs-mode: t
 * End:
 *
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
 * :indentSize=8:tabSize=8:noTabs=false:
 */
